10 Khái Niệm Docker Cốt Lõi Được Giải Thích Trong 10 Phút

**10 Khái Niệm Docker Cốt Lõi Được Giải Thích Trong 10 Phút**

Giới thiệu

Docker đã đơn giản hóa cách chúng ta xây dựng và triển khai ứng dụng. Tuy nhiên, khi học Docker, các thuật ngữ có thể gây khó hiểu. Bạn sẽ thường nghe đến “image”, “container”, “volume” mà chưa thực sự hiểu chúng liên kết với nhau thế nào. Bài viết này sẽ giúp bạn nắm vững các khái niệm cốt lõi của Docker.

Hãy bắt đầu.

1. Docker Image

Docker Image là một sản phẩm đóng gói chứa mọi thứ ứng dụng của bạn cần để chạy: mã nguồn, môi trường thực thi, thư viện, biến môi trường và các tệp cấu hình.

Image có tính bất biến. Một khi đã được tạo, nó sẽ không thay đổi. Điều này đảm bảo ứng dụng của bạn chạy nhất quán trên máy tính của bạn, máy đồng nghiệp hay trong môi trường sản xuất, từ đó loại bỏ lỗi do khác biệt môi trường.

Bạn xây dựng một image từ Dockerfile. Dockerfile đóng vai trò như một công thức, định nghĩa cách tạo ra image đó:

docker build -t my-python-app:1.0 .

Cờ -t dùng để gán nhãn (tag) – tức là đặt tên và phiên bản – cho image của bạn. Dấu . chỉ định Docker tìm Dockerfile trong thư mục hiện tại. Sau khi xây dựng, image này trở thành một khuôn mẫu có thể tái sử dụng cho ứng dụng của bạn.

2. Docker Container

Container là một thể hiện (instance) đang chạy của một image. Đây chính là môi trường biệt lập nơi ứng dụng của bạn thực thi.

docker run -d -p 8000:8000 my-python-app:1.0

Cờ -d chạy container ở chế độ nền (detached). -p 8000:8000 ánh xạ cổng 8000 trên máy chủ của bạn tới cổng 8000 trong container, cho phép truy cập ứng dụng tại localhost:8000.

Bạn có thể chạy nhiều container độc lập từ cùng một image. Đây là cách để kiểm thử nhiều phiên bản song song hoặc mở rộng quy mô ngang bằng cách chạy nhiều bản sao của cùng một ứng dụng.

Container rất gọn nhẹ. Không giống máy ảo, chúng không khởi động toàn bộ hệ điều hành. Chúng khởi động chỉ trong vài giây và chia sẻ kernel của máy chủ.

3. Dockerfile

Dockerfile chứa các chỉ dẫn để xây dựng một image. Đó là một tệp văn bản hướng dẫn Docker cách thiết lập môi trường cho ứng dụng của bạn.

Đây là một Dockerfile mẫu cho ứng dụng Flask:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

Phân tích từng lệnh:

  • FROM python:3.11-slim — Bắt đầu với một image cơ sở đã cài đặt Python 3.11. Biến thể “slim” có kích thước nhỏ hơn image tiêu chuẩn.
  • WORKDIR /app — Đặt thư mục làm việc thành /app. Các lệnh tiếp theo sẽ chạy từ đây.
  • COPY requirements.txt . — Sao chép tệp requirements.txt trước.
  • RUN pip install --no-cache-dir -r requirements.txt — Cài đặt các phụ thuộc Python. Cờ --no-cache-dir giúp giảm kích thước image.
  • COPY . . — Sao chép phần còn lại của mã ứng dụng.
  • EXPOSE 8000 — Khai báo rằng ứng dụng sử dụng cổng 8000.
  • CMD ["python", "app.py"] — Định nghĩa lệnh mặc định sẽ chạy khi container khởi động.

Thứ tự các lệnh này rất quan trọng đối với tốc độ xây dựng, đó là lý do chúng ta cần hiểu về các lớp (layer).

4. Các Lớp Image (Image Layers)

Mỗi lệnh trong Dockerfile tạo ra một lớp mới. Các lớp này xếp chồng lên nhau để tạo thành image cuối cùng.

Docker cache từng lớp. Khi bạn xây dựng lại image, Docker kiểm tra xem mỗi lớp có cần tạo lại không. Nếu không có gì thay đổi, nó sẽ tái sử dụng lớp đã cache thay vì xây dựng lại.

Bí mật:  7 Trình Duyệt AI Tác Nhân Hàng Đầu Đáng Chú Ý Năm 2026

Đó là lý do chúng ta sao chép requirements.txt trước mã nguồn. Các phụ thuộc thường ít thay đổi hơn so với mã nguồn ứng dụng. Khi bạn sửa app.py, Docker tái sử dụng các lớp đã cache (đã cài đặt phụ thuộc) và chỉ xây dựng lại các lớp sau lệnh sao chép mã.

Cấu trúc lớp từ Dockerfile trên:

  1. Image Python cơ sở (FROM)
  2. Đặt thư mục làm việc (WORKDIR)
  3. Sao chép requirements.txt (COPY)
  4. Cài đặt phụ thuộc (RUN pip install)
  5. Sao chép mã ứng dụng (COPY)
  6. Khai báo cổng (EXPOSE)
  7. Lệnh mặc định (CMD)

Nếu chỉ thay đổi mã Python, Docker chỉ xây dựng lại các lớp 5–7. Các lớp 1–4 được lấy từ cache, giúp việc xây dựng nhanh hơn rất nhiều. Hiểu về lớp giúp bạn viết Dockerfile hiệu quả. Nguyên tắc là đặt các tệp hay thay đổi ở cuối và các phần phụ thuộc ít thay đổi ở đầu.

5. Docker Volumes

Container có tính chất tạm thời (ephemeral). Khi bạn xóa một container, mọi thứ bên trong, bao gồm dữ liệu do ứng dụng tạo ra, sẽ bị mất.

Docker Volumes giải quyết vấn đề này. Chúng là các thư mục được lưu trữ bên ngoài hệ thống tệp của container, do đó vẫn tồn tại ngay cả khi container bị xóa.

docker run -d \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:15

Lệnh này tạo một volume có tên postgres-data và gắn kết (mount) nó vào /var/lib/postgresql/data bên trong container. Các tệp cơ sở dữ liệu của bạn sẽ được giữ nguyên qua các lần khởi động lại và xóa container.

Bạn cũng có thể gắn thư mục từ máy chủ, rất hữu ích cho việc phát triển:

docker run -d \
  -v $(pwd):/app \
  -p 8000:8000 \
  my-python-app:1.0

Lệnh này gắn thư mục hiện tại của bạn vào container tại /app. Thay đổi bạn thực hiện trên các tệp ở máy chủ sẽ xuất hiện ngay lập tức trong container, cho phép phát triển trực tiếp mà không cần xây dựng lại image.

Có ba loại gắn kết (mount):

  • Named volumes (postgres-data:/path) — Được Docker quản lý, tốt nhất cho dữ liệu sản xuất.
  • Bind mounts (/host/path:/container/path) — Gắn bất kỳ thư mục máy chủ nào, tốt cho phát triển.
  • tmpfs mounts — Lưu trữ dữ liệu chỉ trong bộ nhớ (RAM), hữu ích cho các tệp tạm thời.

6. Docker Hub

Docker Hub là kho lưu trữ công cộng nơi lưu trữ và chia sẻ các Docker image. Khi bạn viết FROM python:3.11-slim, Docker sẽ kéo (pull) image đó từ Docker Hub.

Bạn có thể tìm kiếm image:

docker search redis

Và kéo chúng về máy:

docker pull redis:7-alpine

Bạn cũng có thể đẩy (push) image của riêng mình lên để chia sẻ hoặc triển khai:

docker tag my-python-app:1.0 username/my-python-app:1.0
docker push username/my-python-app:1.0

Docker Hub lưu trữ các image chính thức cho phần mềm phổ biến như PostgreSQL, Redis, Nginx, Python và hàng nghìn phần mềm khác. Chúng được duy trì bởi chính nhà phát triển và tuân theo các phương pháp hay nhất.

Đối với dự án riêng tư, bạn có thể tạo kho lưu trữ riêng tư trên Docker Hub hoặc sử dụng các dịch vụ khác như Amazon ECR, Google Container Registry hoặc Azure Container Registry.

7. Docker Compose

Các ứng dụng thực tế thường cần nhiều dịch vụ. Một ứng dụng web điển hình có thể có backend Python, cơ sở dữ liệu PostgreSQL, bộ nhớ đệm Redis và một tiến trình xử lý nền.

Docker Compose cho phép bạn định nghĩa tất cả các dịch vụ này trong một tệp cấu hình duy nhất (định dạng YAML) và quản lý chúng cùng nhau.

Tạo tệp docker-compose.yml:

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
      - REDIS_URL=redis://cache:6379
    depends_on:
      - db
      - cache
    volumes:
      - .:/app
  db:
    image: postgres:15-alpine
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
  cache:
    image: redis:7-alpine
volumes:
  postgres-data:

Khởi động toàn bộ hệ thống ứng dụng bằng một lệnh:

docker-compose up -d

Lệnh này khởi động ba container: web, dbcache. Docker Compose tự động xử lý mạng: dịch vụ web có thể truy cập cơ sở dữ liệu tại tên máy chủ db và Redis tại cache.

Để dừng mọi thứ:

docker-compose down

Để xây dựng lại sau khi thay đổi mã:

docker-compose up -d --build

Docker Compose đóng vai trò thiết yếu cho môi trường phát triển. Thay vì cài đặt PostgreSQL và Redis trực tiếp trên máy, bạn có thể chạy chúng trong container chỉ với một lệnh.

Bí mật:  Sự Kết Thúc của Công Việc Như Chúng Ta Từng Biết

8. Mạng Container (Container Networks)

Khi một ứng dụng bao gồm nhiều container, các container này cần giao tiếp với nhau. Docker tạo ra các mạng ảo để kết nối các container này.

Theo mặc định, Docker Compose tạo một mạng cho tất cả các dịch vụ trong docker-compose.yml. Các container sử dụng tên dịch vụ làm tên máy chủ. Trong ví dụ trên, container web kết nối đến PostgreSQL bằng db:5432db là tên dịch vụ.

Bạn cũng có thể tạo mạng tùy chỉnh thủ công:

docker network create my-app-network
docker run -d --network my-app-network --name api my-python-app:1.0
docker run -d --network my-app-network --name cache redis:7

Bây giờ container api có thể truy cập Redis tại cache:6379. Docker cung cấp một số trình điều khiển mạng, phổ biến nhất là:

  • bridge — Mạng mặc định cho các container trên một máy chủ đơn lẻ.
  • host — Container sử dụng trực tiếp mạng của máy chủ (không có sự cách ly mạng).
  • none — Container không có quyền truy cập mạng.

Mạng cung cấp tính cách ly. Các container trên các mạng khác nhau không thể giao tiếp trừ khi được kết nối một cách rõ ràng. Điều này hữu ích cho bảo mật, vì bạn có thể tách biệt các mạng dành cho frontend, backend và cơ sở dữ liệu.

Để xem tất cả các mạng:

docker network ls

Để kiểm tra chi tiết một mạng và các container được kết nối:

docker network inspect my-app-network

9. Biến Môi Trường (Environment Variables) và Docker Secrets

Mã hóa cứng cấu hình là cách làm đầy rủi ro. Mật khẩu cơ sở dữ liệu không nên giống nhau giữa môi trường phát triển và sản xuất. Khóa API chắc chắn không nên nằm trong kho mã nguồn.

Docker giải quyết vấn đề này bằng biến môi trường. Truyền chúng vào lúc chạy với cờ -e, và container của bạn nhận được cấu hình cần thiết mà không cần nhúng giá trị vào image.

Docker Compose làm điều này gọn gàng hơn bằng cách tham chiếu đến tệp .env, giữ bí mật ngoài hệ thống kiểm soát phiên bản. Bạn có thể hoán đổi bằng .env.production khi triển khai.

Docker Secrets là một giải pháp nâng cao cho môi trường sản xuất, đặc biệt trong chế độ Swarm. Khác với biến môi trường — có thể lộ ra trong nhật ký — các “bí mật” được mã hóa cả khi truyền và lưu trữ, sau đó được gắn dưới dạng tệp trong container. Chỉ các dịch vụ được cấp quyền mới có thể truy cập chúng. Chúng được thiết kế để lưu trữ thông tin nhạy cảm như mật khẩu, mã thông báo, chứng chỉ – những thứ có thể gây hậu quả nghiêm trọng nếu bị rò rỉ.

Nguyên tắc rất đơn giản: tách biệt mã khỏi cấu hình. Sử dụng biến môi trường cho cấu hình thông thường và Docker Secrets cho dữ liệu nhạy cảm.

10. Kho Lưu Trữ Container (Container Registry)

Docker Hub phù hợp cho image công khai, nhưng bạn không muốn image ứng dụng nội bộ của mình bị công khai. Kho lưu trữ container là nơi lưu trữ riêng tư cho Docker image của bạn. Các lựa chọn thông dụng bao gồm:

  • Docker Hub (kho riêng tư, bản miễn phí có giới hạn)
  • Amazon ECR
  • Google Container Registry (GCR)
  • Azure Container Registry (ACR)
  • Các kho tự lưu trữ như Harbor hoặc GitLab Container Registry
Bí mật:  Chiến lược tìm kiếm thương hiệu trong tương lai: Tối ưu sự hiện diện với LLMs

Với mỗi tùy chọn, quy trình cơ bản để đẩy (push), kéo (pull) và sử dụng image là tương tự. Ví dụ với ECR:

Máy cục bộ hoặc hệ thống CI/CD của bạn trước tiên cần xác thực với ECR. Sau đó, image Docker được gắn thẻ (tag) đầy đủ với địa chỉ kho lưu trữ của bạn (ví dụ: 123456789.dkr.ecr.region.amazonaws.com/my-app:v1.0). Bước này cho Docker biết image sẽ được lưu ở đâu.

Image sau đó được đẩy lên kho lưu trữ ECR riêng tư. Tại đây, nó được lưu trữ tập trung, được quản lý phiên bản và sẵn sàng cho các hệ thống được ủy quyền.

Các máy chủ sản xuất xác thực với ECR và kéo (pull) image từ kho lưu trữ riêng tư này. Điều này đảm bảo quy trình triển khai của bạn vừa nhanh vừa an toàn. Thay vì tốn thời gian xây dựng image trực tiếp trên máy chủ sản xuất (và cần quyền truy cập mã nguồn), bạn chỉ cần xây dựng một lần, đẩy lên kho lưu trữ, rồi kéo xuống để chạy trên mọi máy chủ.

Nhiều hệ thống CI/CD (như GitHub Actions) có tích hợp sẵn để tự động hóa quy trình xây dựng, đẩy image lên kho lưu trữ và kích hoạt triển khai.

Tổng kết

Mười khái niệm này hình thành nền tảng cốt lõi của Docker. Đây là cách chúng được vận hành trong một quy trình làm việc điển hình:

  1. Viết một Dockerfile với các chỉ dẫn cho ứng dụng của bạn.
  2. Xây dựng một Image từ Dockerfile đó.
  3. Chạy một Container từ image.
  4. Sử dụng Volumes để lưu trữ dữ liệu lâu dài.
  5. Sử dụng Biến môi trườngDocker Secrets cho cấu hình và thông tin nhạy cảm.
  6. Tạo docker-compose.yml cho các ứng dụng đa dịch vụ.
  7. Để các Mạng Docker tự động kết nối các container của bạn.
  8. Đẩy image của bạn lên một Kho lưu trữ Container.
  9. Kéo và chạy nó ở bất cứ đâu.

Hãy bắt đầu bằng cách đóng gói một tập lệnh Python đơn giản. Thêm các phụ thuộc với tệp requirements.txt. Sau đó, mở rộng bằng cách giới thiệu một cơ sở dữ liệu thông qua Docker Compose. Mỗi bước đều xây dựng dựa trên các khái niệm trước đó. Docker sẽ không còn phức tạp một khi bạn nắm vững những nguyên tắc cơ bản này. Nó đơn giản chỉ là một công cụ để đóng gói ứng dụng một cách nhất quán và chạy chúng trong các môi trường biệt lập.

Chúc bạn khám phá vui vẻ!

Tags:
Tags: docker, docker core concepts, devops

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top