Xin chào ! Nếu đây là lần đầu tiên bạn đến với diễn đàn, xin vui lòng danh ra một phút bấm vào đây để đăng kí và tham gia thảo luận cùng VnPro.
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Docker Image và Container – Đừng nhầm "bản thiết kế" với "thứ đang chạy"

    Docker Image và Container – Đừng nhầm "bản thiết kế" với "thứ đang chạy"


    Một trong những nhầm lẫn phổ biến nhất khi mới học Docker là:

    Docker Image và Docker Container có phải cùng một thứ không?

    Không.

    Có thể hiểu rất nhanh:
    Image là thứ được lưu trữ. Container là một instance đang chạy được tạo ra từ Image.

    Nếu Image giống như một "template" bất biến, thì Container là phiên bản thực tế được khởi tạo từ template đó.
    Docker Image là gì?


    Container Image là một tập hợp dữ liệu được lưu trên storage, chứa những thành phần cần thiết để ứng dụng có thể chạy:
    • Application
    • Runtime
    • Libraries
    • Dependencies
    • Một phần filesystem cần thiết

    Ví dụ chúng ta có:
    httpd:2.4
    nginx:latest
    python:3.12-slim
    myapp:v1.0

    Đây đều là Images, chưa phải các ứng dụng đang chạy.

    Image thường được tạo tại Build Stage của CI/CD Pipeline, sau đó được đưa lên Container Registry.
    Source Code


    CI/CD Build


    Docker Image


    Container Registry
    Container là gì?


    Muốn ứng dụng thực sự chạy, chúng ta phải tạo Container từ Image.
    Docker Image

    docker run

    Container


    Running Process

    Một Image có thể tạo ra nhiều Container:
    myapp:v1

    ┌────────┼────────┐
    ▼ ▼ ▼
    Container 1 Container 2 Container 3

    Đây chính là một trong những cơ sở để thực hiện Horizontal Scaling – Scale Out mà chúng ta đã nói đến trong 12-Factor App.
    Container không phải một Virtual Machine nhỏ


    Bên trong Container có một hoặc nhiều Process, nhưng các Process này được cách ly khỏi các Process khác trên Host.

    Chúng có góc nhìn giới hạn đối với:
    • Process
    • Filesystem
    • Networking
    • Resources

    Trên Linux, Docker sử dụng các cơ chế của kernel như Namespacescgroups để tạo ra sự cách ly và kiểm soát tài nguyên.

    Điểm rất quan trọng:
    Container không mang theo kernel riêng như Virtual Machine.

    Ví dụ Host chạy một Linux distribution, Container có thể cung cấp user-space của Debian, Ubuntu hoặc một distribution phù hợp với ứng dụng, nhưng các Linux Container vẫn sử dụng kernel của Host.

    Đây là lý do Container nhỏ và khởi động nhanh hơn VM.
    docker pull – Lấy Image về máy


    Muốn chạy Container, Docker Engine trước tiên phải có Image.

    Chúng ta có thể chủ động tải Image:
    docker pull httpd

    Quá trình sẽ là:
    Container Registry

    docker pull


    Local Image Cache

    Nếu chạy docker run mà Image chưa tồn tại local, Docker thông thường cũng sẽ tự động Pull Image cần thiết từ Registry.
    docker run – Từ Image thành Container


    Lệnh cơ bản:
    docker run httpd

    Docker sẽ tạo Container từ Image httpd và khởi động Process mặc định đã được định nghĩa trong Image.

    Trong thực tế, chúng ta thường cần thêm một số option.

    Ví dụ:
    docker run -d --name web01 -p 8080:80 httpd

    Hãy bóc tách câu lệnh này. -d – Detached Mode

    -d

    Container chạy dưới background thay vì chiếm Terminal hiện tại.
    --name – Đặt tên Container

    --name web01

    Container sẽ có tên:
    web01

    Thay vì phải nhớ một Container ID dài, chúng ta có thể quản lý nó bằng tên.

    Tên Container cũng hữu ích trong Docker networking: các Container trên cùng một user-defined network có thể phân giải tên của nhau thông qua DNS tích hợp của Docker.
    -p – Publish Port

    -p 8080:80

    Đây là phần người mới học Docker rất dễ nhầm.

    Nó có nghĩa:
    Client


    Host:8080


    Container:80


    Apache HTTP Server

    Port 8080 của Host được publish/map tới Port 80 của Container.

    Sau đó người dùng có thể truy cập:
    http://<Docker-Host>:8080

    Một lưu ý về thuật ngữ: EXPOSE trong Dockerfile chủ yếu mô tả/document port mà ứng dụng dự kiến lắng nghe; còn docker run -p mới thực hiện việc publish port của Container ra Host.

    Điều này liên hệ trực tiếp với yếu tố Port Binding trong 12-Factor App mà chúng ta đã học.
    -it – Khi muốn tương tác với Container


    Đôi khi chúng ta không muốn chạy Web Server mà muốn vào bên trong môi trường Container để kiểm tra.

    Có thể sử dụng:
    docker run -it ubuntu bash

    Trong đó:
    -i → Interactive
    -t → Allocate pseudo-TTY

    và:
    bash

    là command được yêu cầu chạy trong Container.

    Khi đó thay vì khởi động một service theo mặc định của Image, Docker chạy Bash và cho phép chúng ta tương tác với môi trường bên trong Container.

    Lưu ý rằng command chỉ chạy được nếu chương trình đó thực sự tồn tại trong Image.
    Tại sao nhiều Container Image không có đầy đủ công cụ Linux?


    Bạn vào một Container và thử:
    ping
    vim
    curl
    ssh

    nhưng phát hiện một số lệnh không tồn tại.

    Điều này không nhất thiết là lỗi.

    Container Image thường được thiết kế theo nguyên tắc:
    Chỉ chứa những gì ứng dụng thực sự cần.

    Ít package hơn đồng nghĩa với:
    • Image nhỏ hơn.
    • Download nhanh hơn.
    • Build nhanh hơn.
    • Ít dependency hơn.
    • Giảm Attack Surface.
    • Giảm số lượng package cần vá lỗi.

    Đó là lý do các Image như slim, alpine hoặc các distroless images thường được sử dụng để tối ưu Container cho Production.
    Docker Engine đứng ở đâu trong toàn bộ kiến trúc?


    Khi bạn gõ:
    docker run ...

    Docker CLI không tự mình thực hiện tất cả công việc.

    Mô hình tổng quát là:
    Docker Client

    Docker API


    Docker Engine / Daemon

    ├──── Container Images

    ├──── Containers

    ├──── Networks

    └──── Volumes

    Docker Client gửi yêu cầu tới Docker Engine thông qua API, còn Engine chịu trách nhiệm thực hiện các thao tác liên quan đến Image, Container, Network và Volume.
    Kết nối lại với CI/CD


    Bây giờ chúng ta có thể nhìn Docker dưới góc độ DevSecOps:
    Developer


    Git Commit


    CI Pipeline

    ├── Static Analysis
    ├── Unit Test
    └── docker build


    Docker Image


    Container Registry

    docker pull


    docker run


    Container

    Build Stage tạo Image.

    Registry lưu và phân phối Image.

    Run Stage tạo Container từ Image.

    Và từ cùng một Image đã được kiểm thử, chúng ta có thể tạo nhiều Container giống nhau trên Development, Staging hay Production.

    Đây chính là điểm Docker kết nối rất đẹp với những nguyên tắc chúng ta đã học trong chuỗi 12-Factor App: Build–Release–Run, Dev/Prod Parity, Port Binding, Stateless Processes, Concurrency và Disposability.

    Hiểu rõ Image ≠ Container là bước đầu tiên để hiểu Docker. Bước tiếp theo quan trọng hơn nữa là hiểu Docker tạo Image như thế nào thông qua Dockerfile và hệ thống Layers, bởi đây chính là nơi chúng ta có thể tối ưu tốc độ Build, kích thước Image và cả bảo mật cho CI/CD Pipeline.
    Đặng Quang Minh, CCIE#11897 (Enterprise Infrastructure, Wireless, Automation, AI), CCSI#31417

    Email : dangquangminh@vnpro.org
    https://www.facebook.com/groups/vietprofessional/
Working...
X