Part 4 – Kiến trúc cơ bản của docker

By | 30 December, 2018

Khi tìm hiểu về bất cứ hệ thống hay một opensource hoặc bất cứ một phần mềm gì mới, tôi thường đọc khái niệm, tiếp đó là tìm hiểu kiến trúc của nó và cuối cùng là tiến hành đọc documentation và tiến hành thử nghiệm nó. Các phần trước chúng ta đã đi qua các khái niệm cơ bản trong docker, phần này chúng ta sẽ bàn qua về kiến trúc cơ bản của nó.

Tổng quan về các thành phần trong Docker

Phần core của Docker bao gồm Docker Engine, Docker Container, Docker image, Docker storage, Docker Client, Docker daemon, v.v. Hãy thảo luận về các thành phần của Docker.

Giới thiệu về Docker Engine

Docker engine là một phần của Docker cái dùng để tạo và chạy các container Docker. Container docker là một phiên bản chạy trực tiếp của image docker. Docker Engine là một ứng dụng dựa trên client-server với các thành phần sau:

  • Một server là một dịch vụ chạy liên tục được gọi là quá trình daemon.
  • API REST có giao diện cho các chương trình sử dụng nói chuyện với daemon và hướng dẫn nó phải làm gì.
  • Một client giao diện dòng lệnh (docker cli).

Client giao diện dòng lệnh sử dụng API REST Docker để tương tác với daemon Docker thông qua các lệnh CLI. Nhiều ứng dụng Docker khác cũng sử dụng API và CLI. aemon tạo và quản lý image Docker, container, network và volume.

Docker Daemon (dockerd)

Quá trình daemon của docker được sử dụng để kiểm soát và quản lý các container. Trình daemon Docker chỉ lắng nghe các yêu cầu API của Docker và xử lý các image, image, network và volume của Docker. Nó cũng liên lạc với các trình daemon khác để quản lý các dịch vụ Docker.

Sử dụng Docker Client (CL)

Docker client là dịch vụ chính sử dụng mà người dùng Docker giao tiếp với Docker. Khi chúng ta sử dụng các lệnh của Docker chạy, thì client sẽ gửi các lệnh này đến dockerd để thực hiện chúng.

Lệnh được sử dụng bởi docker phụ thuộc vào API Docker. Trong Docker, client có thể tương tác với nhiều hơn một tiến trình daemon.

Docker Image

Một image Docker được tạo thành từ nhiều layer khác nhau. Một người dùng tổng hợp mỗi image Docker bao gồm các thư viện hệ thống, công cụ và các tệp và phụ thuộc khác cho code thực thi. Các nhà phát triển image có thể sử dụng lại các layer của các image khác cho các dự án khác nhau. Tái sử dụng giúp tiết kiệm thời gian, vì người dùng không phải tạo mọi thứ trong image.

Hầu hết, một image được dựa trên một image khác, với một số tùy chỉnh bổ sung trong image.

Chúng ta có thể xây dựng một image dựa trên hình ảnh centos, có thể cài đặt máy chủ web Nginx với các chi tiết ứng dụng và cấu hình cần thiết để ứng dụng chạy.

Chúng ta có thể tạo image của riêng mình hoặc chỉ sử dụng những image được tạo bởi người khác và được release trên docker hub. Để xây image của riêng chúng ta rất đơn giản: Tạo Dockerfile với một số cú pháp chứa các bước cần thiết để tạo image và thực thi để chạy nó.

Mỗi hướng dẫn trong Dockerfile tạo ra một layer mới trong image. Nếu chúng ta cần sửa đổi Dockerfile, chúng ta có thể làm tương tự và build lại image, chỉ các layer đã thay đổi sẽ được build lại.

Đây là lý do tại sao image rất nhẹ, nhỏ và nhanh khi so sánh với các công nghệ ảo hóa khác.

Docker registry

Docker Registry sẽ lưu trữ image Docker. Chúng ta có thể tạo registry riêng của chúng ta.

Khi chúng ta thực hiện các lệnh docker pulldocker run, các image nếu không có ở local sẽ được pull về từ registry.

Sử dụng lệnh Docker push, image có thể được đẩy registry đã được cấu hình của chúng ta.

Docker container

Một container là 1 instance của một image. Chúng ta có thể tạo, chạy, dừng hoặc xóa một container bằng Docker CLI. Chúng ta có thể kết nối một container với nhiều network hoặc thậm chí tạo một image mới dựa trên trạng thái hiện tại của nó.

Theo mặc định, một container được cô lập (isolate) với các container khác. Chúng ta có thể liên kết chúng với nhau bằng cách sử dụng network. Một container được xác định bởi các tùy chọn image hoặc cấu hình mà chúng ta cung cấp trong quá trình tạo hoặc chạy nó.

Docker Namespaces

Docker sử dụng một dịch vụ có tên namespace cung cấp cho các môi trường bị cô lập gọi là container. Khi chúng ta chạy một container, Docker tạo một tập hợp các namespace cho container đó. Các namespace cung cấp một layer bị cô lập. Một số thành phần namespace layer là:

  • Namespace PID cung cấp sự cô lập để phân bổ process, liệt kê các process với các chi tiết của chúng. Trong namespace mới được tạo từ các process khác trong namespace, “parent” của nó vẫn thấy tất cả các process trong namespace con.
  • Network namespace cô lập các network interface controllers, quy tắc tường lửa của bảng IP, bảng định tuyến, vv Các network namespace có thể được kết nối với nhau bằng thiết bị Ethernet ảo.

Docker Control Groups

Docker Engine trong Linux dựa trên các nhóm điều khiển được đặt tên. Một nhóm giới hạn ứng dụng trong một bộ tài nguyên được xác định trước.

Các nhóm điều khiển được sử dụng bởi Docker Engine để chia sẻ tài nguyên phần cứng có sẵn cho các container.

Sử dụng các nhóm điều khiển, chúng ta có thể xác định bộ nhớ khả dụng cho một container cụ thể.

Docker storage

Bạn có thể lưu trữ dữ liệu trong layer có thể ghi của một container nhưng nó yêu cầu drive storage. Không bền vững, data có thể bị mất bất cứ khi nào container không chạy. Hơn nữa, không dễ để chuyển dữ liệu này. Về vấn đề storage, Docker cung cấp bốn tùy chọn:

  • Data volume : Volume cung cấp khả năng tạo lưu trữ liên tục (persistent storage), với khả năng đổi tên volume, liệt kê volume và cũng liệt kê container được liên kết với volume. Data volume nằm trên hệ thống tệp máy chủ, bên ngoài các container với cơ chế copy on write khá hiệu quả.
  • Data Volume Container : Data Volume Container là một cách tiếp cận khác trong đó một container chuyên dụng lưu trữ một volume và gắn volume đó vào các container khác. Trong trường hợp này, container volume độc lập với container ứng dụng và do đó nó có thể được chia sẻ trên nhiều container.
  • Directory Mounts: Một tùy chọn khác là gắn thư mục cục bộ của server vào một container. Trong các trường hợp được đề cập trước đó, các volume sẽ phải nằm trong thư mục volumec của Docker, trong khi đó, khi nói đến directory mounts, bất kỳ thư mục nào trên server có thể được sử dụng như là 1 source cho volume.
  • Storage Plugin : Cung cấp khả năng kết nối với các nền tảng lưu trữ bên ngoài. Các plugin này ánh xạ lưu trữ từ server sang nguồn bên ngoài như mảng lưu trữ hoặc thiết bị lưu trữ. Có thể tìm thấy danh sách các plugin lưu trữ trên trang Plugin của Docker.

Có các storage plugin từ các nhà cung cấp khác nhau để tự động hóa quy trình cung cấp storage. Ví dụ,

  • HPE 3PAR
  • EMC (ScaleIO, XtremIO, VMAX, Isilon)
  • Netapp

Ngoài ra còn có các plugin hỗ trợ các nhà cung cấp public cloud như:

  • Azure File storage
  • Google compute platform.
  • Amazon File storage.

Union File Systems

Các hệ thống tệp Union là một hệ thống tệp được sử dụng bằng cách tạo các layer, làm cho chúng nhẹ và nhanh hơn. Docker Engine sử dụng hệ thống tập tin union cung cấp các building block cho container.

Docker Engine sử dụng nhiều biến thể UnionFS, một số bao gồm AUFS, btrfs, vfs, Device Mapper, v.v.

Sử dụng Dockerfile

Docker file là một tệp văn bản bao gồm tất cả các lệnh để người dùng có thể gọi trên dòng lệnh để xây dựng một image. Sử dụng một Docker image base thêm và sao chép các tập tin, chạy các lệnh và hiển thị các cổng để tạo thành các image khác.

Docker file có thể được coi là mã nguồn và image để biên dịch cho container của chúng ta để chạy code. Dockerfile là các tệp di động có thể được chia sẻ, lưu trữ và cập nhật theo yêu cầu. Một số lệnh cơ bản(nó được gọi là các instruction, trong bài này tôi gọi nó là các lệnh cho dễ hiểu) trong dockerfile:

  • FROM – Điều này được sử dụng để chỉ định image base bạn sẽ dùng cho image mới. Đây là 1 phần rất quan trọng vì dựng các image khác cần dựa trên 1 image base nào đó. Vì thế nó luôn được định nghĩa đầu tiên trong dockerfile.
  • MAINTAINER – Hướng dẫn này được sử dụng để chỉ ra tác giả của tệp docker và không được thực thi trong quá trình build.
  • RUN – Lệnh này cho phép chúng ta thực thi lệnh trên đầu layer hiện có và tạo một layer mới với kết quả thực hiện lệnh.
  • CMD – Lệnh này không thực hiện bất cứ điều gì trong quá trình xây dựng hình ảnh docker. Nó chỉ xác định các lệnh được sử dụng trong image.
  • LABEL – Lệnh này được sử dụng để gán metadata trong các cặp key-value.
  • EXPOSE – Lệnh này được sử dụng để listen các port của các application bên trong.
  • ENV – Lệnh này được sử dụng để đặt các biến môi trường trong Dockerfile cho container.
  • COPY – Được sử dụng để sao chép các tệp và thư mục từ thư mục cụ thể sang thư mục đích. Dùng để copy file từ ngoài vào trong image, ví dụ như code, file config, data …
  • WORKDIR – Lệnh này được sử dụng để chỉ định thư mục làm việc hiện tại cho lệnh khác, ví dụ: RUN, CMD, COPY, v.v.

Như vậy chúng ta đã thấy các thành phần khác nhau trong kiến ​​trúc Docker và cách chúng hoạt động cùng nhau, chúng ta có thể bắt đầu hiểu được sự gia tăng phổ biến của các container Docker. Chúng ta cũng có thể thấy cách Docker giúp đơn giản hóa việc quản lý hạ tầng bằng cách làm cho các instance nhẹ hơn, nhanh hơn và linh hoạt hơn. Ngoài ra, Docker tách layer ứng dụng khỏi lớp cơ sở hạ tầng và mang lại tính di động, cộng tác và kiểm soát rất cần thiết cho chuỗi phân phối phần mềm. Docker là mẫu kiến ​​trúc chuẩn cho các nhóm DevOps hiện đại và hiểu kiến ​​trúc của nó sẽ giúp bạn tận dụng tối đa các ứng dụng được đóng gói của mình.