Lộ trình
Docker Compose đơn giản hóa việc quản lý các ứng dụng Docker nhiều container, giúp nhà phát triển viết và chạy ứng dụng phức tạp một cách nhẹ nhàng.
Các kỹ sư DevOps tầm trung, lập trình viên backend và nhà phát triển cloud-native, đặc biệt là những người làm việc với microservices hoặc kiến trúc đa dịch vụ, thường đối mặt với thách thức quản lý vô số container liên kết với nhau. Docker Compose giải quyết các phức tạp này, tinh gọn quy trình phát triển và kiểm thử.
Trong bài viết này, bạn sẽ học mọi thứ cần thiết để sử dụng Docker Compose. Nếu bạn mới bắt đầu với Docker, hãy xem Hướng dẫn Docker cho Người Mới Bắt Đầu.
Docker Compose là gì?
Docker Compose là công cụ được thiết kế để định nghĩa và điều phối các ứng dụng Docker nhiều container thông qua một tệp cấu hình YAML duy nhất.
Với Compose, bạn có thể dễ dàng chỉ định services, networks, volumes, thiết lập môi trường và các phụ thuộc. Nó lý tưởng cho phát triển cục bộ, môi trường kiểm thử, tạo mẫu nhanh và các môi trường sản xuất nhỏ.
Các trường hợp sử dụng phổ biến của Docker Compose bao gồm tạo môi trường cục bộ phản chiếu hệ thống thực tế, như kiến trúc microservices. Bằng cách định nghĩa rõ ràng cách các thành phần tương tác, Compose mang lại tính nhất quán, dễ sử dụng và chu kỳ lặp nhanh hơn.
Bạn có thể thắc mắc vì sao không dùng Kubernetes. Trước hết, đó là giải pháp quá mức cần thiết cho các dự án nhỏ và kiểm thử cục bộ. Như bạn sẽ thấy trong hướng dẫn Kubernetes vs. Docker, Kubernetes phù hợp hơn để quản lý nhiều container trên các cụm. Khóa học Containerization and Virtualization with Docker and Kubernetes của chúng tôi đi sâu vào cách xây dựng và triển khai ứng dụng với Docker và Kubernetes.
Vì sao sử dụng Docker Compose thay vì lệnh Docker thủ công?
Quản lý riêng lẻ nhiều container có thể nhanh chóng trở nên hỗn loạn do:
- Thứ tự phụ thuộc phức tạp,
- Môi trường không nhất quán, và
- Vấn đề khả năng mở rộng.
Với các lệnh thủ công, bạn có nguy cơ mắc lỗi do con người, trôi cấu hình và quy trình làm việc kém hiệu quả.
Docker Compose giúp giải quyết những vấn đề này bằng cách định nghĩa tất cả dịch vụ ứng dụng và phụ thuộc trong một tệp YAML. Điều này mang lại tính nhất quán, khả năng mở rộng và quản lý phụ thuộc dễ dàng, giảm đáng kể sai sót và nâng cao năng suất.
Compose nhanh hơn so với tạo container và kết nối chúng thủ công. Hơn nữa, Compose tạo một mạng mặc định cho việc giao tiếp giữa tất cả container. Ngoài ra, nó quản lý volumes, đảm bảo tự động gắn lại khi thay thế dịch vụ hoặc khởi động lại.
Bạn có thể học cách đóng gói (containerize) ứng dụng học máy với Docker và Kubernetes trong hướng dẫn Cách Đóng Gói Ứng Dụng Bằng Docker.
Sự khác nhau giữa Docker và Docker Compose là gì?
Trong khi Docker là nền tảng để xây dựng, chạy và quản lý container, Docker Compose là công cụ giúp dễ dàng định nghĩa và quản lý nhiều container bằng tệp YAML, chủ yếu là docker-compose.yml.
Docker xử lý các container đơn lẻ, còn Docker Compose cho phép bạn xếp chúng thành một dịch vụ thống nhất. Ví dụ, một ứng dụng có backend, frontend, cơ sở dữ liệu, bộ nhớ đệm, v.v.
Bạn có thể xây dựng và chạy container mà không cần Docker Compose. Tuy nhiên, gom mọi thứ vào một tệp docker-compose.yml sẽ giúp quản lý nhiều container dễ dàng hơn. Nó cũng cho phép khởi chạy ứng dụng trong bất kỳ môi trường nào chỉ với một lệnh.
Hiểu Docker và Docker Compose rất quan trọng để bạn vượt qua các buổi phỏng vấn sắp tới. Hãy sẵn sàng bằng cách khám phá 26 Câu Hỏi Phỏng Vấn Docker Hàng Đầu và Đáp Án cho 2025.
Những điều căn bản về Docker Compose
Trước khi đi vào chi tiết thực hành, việc hiểu các nguyên tắc cốt lõi và cú pháp của Docker Compose là cần thiết. Trước khi dùng Compose, hãy đảm bảo bạn đã cài Docker theo hướng dẫn trong Cài Đặt Docker trên Ubuntu: Từ Thiết Lập đến Container Đầu Tiên.
Khung khái niệm
Docker Compose trừu tượng hóa sự phức tạp của điều phối container cho phát triển cục bộ và các triển khai đơn giản hơn. Với tệp Compose định dạng YAML, bạn khai báo các dịch vụ cần thiết, định nghĩa phụ thuộc, chỉ định networks, volumes, biến môi trường và nhiều hơn nữa. Compose quản lý hiệu quả việc khởi động, dừng, mở rộng và kết nối các dịch vụ này.
Cú pháp Compose cốt lõi
Docker Compose xoay quanh cú pháp YAML đơn giản. Các thành phần chính gồm:
servicesđể định nghĩa các ứng dụng đóng gói trong containerimageshoặc ngữ cảnhbuildđể chỉ định containerportsđể xuất dịch vụvolumesđể lưu trữ dữ liệu bền vữngnetworksđể giao tiếp giữa các dịch vụ
Định nghĩa Dịch vụ và Kiến trúc Ứng dụng
Các tệp Compose biểu diễn các dịch vụ của ứng dụng và kết nối giữa chúng.
Định nghĩa services
Services là lõi của tệp Compose. Bạn có thể định nghĩa rõ ràng và đặt tên nhiều dịch vụ (như frontend web, cơ sở dữ liệu, dịch vụ bộ nhớ đệm), chỉ định phụ thuộc qua các từ khóa đơn giản như depends_on để kiểm soát thứ tự khởi động container.
Kiến thức cơ bản về mạng
Docker Compose tự động tạo các mạng mặc định để hỗ trợ giao tiếp giữa những dịch vụ được định nghĩa. Nhà phát triển cũng có thể chỉ định mạng tùy chỉnh khi cần để tăng cô lập hoặc đáp ứng yêu cầu mạng chi tiết.
Quản lý volumes
Volumes cho phép dữ liệu tồn tại vượt ngoài vòng đời container. Bạn có thể chỉ định volumes có tên hoặc gắn thư mục từ host vào container, đảm bảo cơ sở dữ liệu, log hoặc dữ liệu trạng thái khác được lưu bền vững.
Biến môi trường
Compose đơn giản hóa việc truyền biến môi trường và bí mật vào container một cách an toàn. Nó hỗ trợ khai báo trực tiếp dưới các dịch vụ và tham chiếu các biến được lưu trong tệp env bên cạnh tệp compose để giữ an toàn và tách biệt các giá trị nhạy cảm khỏi định nghĩa Docker.
Mở Rộng và Điều Phối với Docker Compose
Docker Compose cũng tinh gọn việc mở rộng và điều phối cơ bản, đặc biệt hữu ích cho các kịch bản kiểm thử tải nhanh hoặc đánh giá dịch vụ song song.
Mở rộng services
Cờ "--scale" của Compose cho phép bạn nhanh chóng khởi chạy nhiều bản sao của dịch vụ. Điều này giúp các kịch bản kiểm thử như đánh giá cân bằng tải hoặc xử lý yêu cầu đồng thời trở nên đơn giản.
Ví dụ, mở rộng container ứng dụng Flask chỉ với một lệnh:
docker-compose up --scale flaskapp=4
Docker Compose so với Docker Swarm và Kubernetes
Trong khi Docker Compose vượt trội ở phát triển cục bộ và thiết lập quy mô nhỏ, nó bị hạn chế trong điều phối đa host ở quy mô sản xuất. Với các kịch bản phức tạp ở quy mô sản xuất trên nhiều host, những bộ điều phối mạnh mẽ hơn như Docker Swarm hoặc Kubernetes là phù hợp, vì chúng cung cấp cân bằng tải mạnh mẽ, tự phục hồi, mạng nâng cao và khả năng mở rộng lớn mà Compose không có.
Bài viết Docker Compose vs. Kubernetes của chúng tôi phân tích chi tiết hơn các khác biệt chính giữa Docker Compose và Kubernetes.
|
Tính năng |
Docker Compose |
Docker Swarm |
Kubernetes |
|
Trường hợp sử dụng chính |
Phát triển cục bộ, ứng dụng nhiều container đơn giản |
Cụm sản xuất nhỏ đến vừa |
Điều phối ở quy mô lớn, cấp độ sản xuất |
|
Hỗ trợ đa host |
Không hỗ trợ |
Tích hợp sẵn |
Hỗ trợ gốc |
|
Khả năng mở rộng |
Chỉ mở rộng thủ công |
Vừa phải, với clustering tích hợp |
Cao, thiết kế cho khối lượng lớn |
|
Cân bằng tải |
Không có bộ cân bằng tải tích hợp |
Định tuyến nội bộ với cân bằng tải |
Khám phá dịch vụ và cân bằng tải nâng cao |
|
Tự phục hồi |
Không tự phục hồi |
Khởi động lại khi lỗi ở mức cơ bản |
Tự khôi phục nâng cao và cập nhật cuốn chiếu |
|
Mạng |
Mạng bridge cơ bản |
Mạng overlay giữa các node |
Mô hình mạng phong phú (CNI) |
|
Độ khó học |
Dễ học |
Độ phức tạp vừa phải |
Cao, với nhiều thành phần và cấu hình |
|
Tích hợp hệ sinh thái |
Công cụ hạn chế |
Công cụ CLI/GUI ở mức vừa |
Hệ sinh thái phong phú (Helm, operators, v.v.) |
|
Tài nguyên tiêu tốn |
Tối thiểu |
Nhẹ |
Nặng hơn, cần nhiều tài nguyên hệ thống |
|
Quản lý trạng thái |
Không có nhận biết trạng thái tích hợp |
Cơ bản qua Raft |
Khai báo, quản lý trạng thái đầy đủ |
|
Kiểu triển khai |
Dựa trên YAML (docker-compose.yml) |
YAML + CLI |
YAML (Deployment, Service, v.v.) |
|
Phù hợp nhất cho |
Máy dev, pipeline CI, demo nhanh |
Nhóm nhỏ, dịch vụ đơn giản trong prod |
Ứng dụng phức tạp, microservices, hạ tầng doanh nghiệp |
Kỹ Thuật Tối Ưu để Sử Dụng Compose Hiệu Quả
Sử dụng Docker Compose hiệu quả bao gồm tối ưu hóa quá trình build, thêm health check và quản lý tài nguyên dịch vụ. Phần này sẽ giúp bạn hiểu rõ hơn các kỹ thuật tối ưu này.
Chiến lược build hiệu quả
Sử dụng build nhiều giai đoạn trong Dockerfile giúp giảm kích thước image Docker, trong khi tận dụng cache build một cách rõ ràng sẽ tăng tốc đáng kể quá trình phát triển và CI.
Health check và chính sách khởi động lại
Compose cho phép bạn định nghĩa health check rõ ràng cho container để duy trì độ tin cậy của ứng dụng. Các chính sách khởi động lại giúp đảm bảo container lỗi sẽ tự động khởi động lại, tăng khả năng chống chịu.
Quản lý giới hạn tài nguyên
Thiết lập giới hạn CPU và bộ nhớ trực tiếp trong YAML của Compose giúp bạn kiểm soát phân bổ tài nguyên, tăng tính dự đoán và hiệu suất sử dụng tài nguyên.
Ví dụ đoạn cấu hình giới hạn tài nguyên:
services:
flaskapp:
image: flask
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
Ví Dụ Thực Tiễn: Ứng Dụng Nhiều Container
Dưới đây là một ví dụ thực tế đơn giản gồm ứng dụng Python Flask kết hợp với Redis:
services:
redis:
image: redis:7
container_name: redis
ports:
- "6379:6379"
restart: always
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 5s
retries: 3
web:
build: .
container_name: flask_app
command: gunicorn app:app --worker-class gevent --bind 0.0.0.0:5000 --timeout 3000
ports:
- "5000:5000"
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
env_file:
- .env
volumes:
- ./shorts:/app/shorts
- ./temp_uploads:/app/temp_uploads
- ./uploads:/app/uploads
restart: always
worker:
build: .
container_name: celery_worker
command: celery -A celery_worker.celery worker --loglevel=info
depends_on:
- redis
environment:
- REDIS_URL=redis://redis:6379/0
env_file:
- .env
volumes:
- ./shorts:/app/shorts
- ./temp_uploads:/app/temp_uploads
- ./uploads:/app/uploads
restart: always
Tệp Docker Compose định nghĩa một ứng dụng nhiều container với ba dịch vụ:
- redis
- web (ứng dụng Flask với Gunicorn)
- worker (Celery worker)
Đối với dịch vụ redis:
- Sử dụng image Redis 7 chính thức.
- Đặt tên container là
redis. - Ánh xạ cổng 6379 trong container sang 6379 trên host.
- Luôn khởi động lại nếu gặp sự cố (restart: always).
- Định nghĩa
healthcheckchạy lệnh ping củaredis-climỗi 30 giây, timeout sau 5 giây và thử lại 3 lần trước khi đánh dấu container không khỏe.
Đối với dịch vụ web:
- Build image từ thư mục hiện tại (
build: .). - Đặt tên container là
flask_app. - Chạy lệnh gunicorn
app:appvới workergevent, bind 0.0.0.0:5000, timeout dài 3000 giây - Ánh xạ cổng 5000 của container sang 5000 trên host.
- Khai báo phụ thuộc vào dịch vụ
redis, đảm bảo Redis khởi động trước. - Thiết lập biến môi trường
REDIS_URLtrỏ đến container Redis nội bộ. - Nạp thêm biến môi trường từ tệp
.env. - Gắn ba thư mục cục bộ vào container:
./shortsvào/app/shorts,./temp_uploadsvào/app/temp_uploads./uploadsvào/app/uploads- Cấu hình luôn khởi động lại nếu gặp sự cố.
Đối với dịch vụ worker:
- Cũng build image từ thư mục hiện tại (build: .), dùng lại cùng Dockerfile với dịch vụ web.
- Đặt tên container:
celery_worker. - Chạy lệnh
celery -A celery_worker.celery worker --loglevel=infođể khởi động Celery worker xử lý tác vụ nền. - Khai báo phụ thuộc vào dịch vụ
redis, đảm bảo Redis khởi động trước. - Thiết lập cùng biến môi trường
REDIS_URLđể kết nối tới broker Redis. - Nạp các biến môi trường khác từ tệp
.env. - Gắn cùng ba thư mục như dịch vụ web, cho phép cả ứng dụng web và worker chia sẻ tệp và nội dung tải lên.
- Cấu hình luôn khởi động lại nếu gặp sự cố.
Khám phá thêm ý tưởng dự án Docker trong hướng dẫn 10 Ý Tưởng Dự Án Docker của chúng tôi.
Xây Dựng và Chạy Ứng Dụng Nhiều Container
Docker Compose cung cấp bộ công cụ trực quan cho các tác vụ container thường nhật:
Build images
Dùng docker compose build để tạo images theo Dockerfile bạn định nghĩa. Chúng tôi trình bày thêm về xây dựng Docker image trong hướng dẫn Cách Học Docker Từ Con Số 0: Hướng Dẫn Cho Chuyên Gia Dữ Liệu.
Chạy services
Sử dụng docker compose up để khởi chạy tất cả dịch vụ được định nghĩa trong tệp compose. Để chạy nền, dùng docker compose up -d. Khóa học Introduction to Docker của chúng tôi đi sâu hơn về chạy container ở chế độ nền.
Xem container đang chạy
Để xem các container đang hoạt động và trạng thái của chúng, dùng docker compose ps để liệt kê tất cả dịch vụ đang chạy.
Dừng services
Dùng docker compose down để dừng các dịch vụ đang chạy.
Xem log
Dùng docker compose logs để kiểm tra log. Bạn có thể chỉ định một container để xem log bằng docker logs container_name. Để stream log, dùng docker compose -f container_name.
Hướng dẫn 18 Lệnh Docker Hàng Đầu để Build, Chạy và Quản Lý Containers của chúng tôi phân tích thêm các lệnh Docker để bạn tự tin quản lý ứng dụng trên nhiều môi trường.
Các Trường Hợp Nâng Cao với Docker Compose
Quy trình Compose có thể thích ứng với các thiết lập phát triển phức tạp hơn hoặc cấu hình môi trường khác nhau.
Cấu hình đa môi trường
Nhiều tệp Compose hoặc tệp ghi đè giúp thiết lập các môi trường khác nhau (phát triển, kiểm thử, sản xuất). Điều này giữ cho định nghĩa dễ bảo trì và dễ đọc, cho phép chỉnh sửa nhanh mà không làm rối cấu hình.
Quản lý phụ thuộc
Trong khi depends_on xử lý thứ tự khởi động cơ bản, các kịch bản phức tạp có thể tích hợp script khởi tạo (như "wait-for-it"), đảm bảo container chỉ khởi động sau khi thỏa các điều kiện cụ thể, chẳng hạn cơ sở dữ liệu sẵn sàng.
Tích hợp với CI/CD
Compose tích hợp dễ dàng vào quy trình tích hợp liên tục, tự động hóa thiết lập môi trường hoàn chỉnh cho kiểm thử. Các nền tảng như GitLab CI và GitHub Actions cung cấp cách tiếp cận gốc hoặc đơn giản để tích hợp Compose, tinh gọn kiểm thử tự động.
Thực hành tốt nhất và Thách thức thường gặp
Bạn có thể tránh các lỗi thường gặp và xây dựng cấu hình dễ bảo trì bằng cách tổ chức và cấu trúc định nghĩa Compose một cách cẩn trọng.
Tổ chức Tệp Compose
Giữ cho tệp Compose rõ ràng và mô-đun. Với dự án đơn giản, một tệp là đủ, nhưng với ứng dụng lớn hơn, hãy cân nhắc tách cấu hình thành nhiều tệp Compose bằng tính năng override. Điều này cho phép:
- Phân tách hợp lý các thành phần (ví dụ,
docker-compose.backend.yml,docker-compose.frontend.yml) - Tùy biến môi trường cục bộ vs. sản xuất dễ dàng hơn
- Tinh gọn kiểm soát phiên bản và cộng tác, vì thay đổi đối với một dịch vụ không ảnh hưởng toàn bộ tệp
Dùng tên dịch vụ có ý nghĩa và thụt lề nhất quán để tệp dễ đọc và theo dõi.
Cạm bẫy tiềm ẩn
Lưu ý những sai sót thường gặp sau:
- Dùng thẻ
latestcho images: Điều này gây khó đoán, vì phiên bản image thực tế có thể thay đổi theo thời gian. Luôn ghim phiên bản image rõ ràng (ví dụ,postgres:15.1) để đảm bảo nhất quán giữa các môi trường. - Hard-code bí mật: Không bao giờ đưa dữ liệu nhạy cảm (ví dụ, API key, mật khẩu) trực tiếp vào tệp Compose. Thay vào đó, dùng biến môi trường, tệp
.env(loại trừ khỏi kiểm soát phiên bản), hoặc công cụ quản lý bí mật như Docker Secrets để xử lý an toàn. - Định nghĩa dịch vụ quá phức tạp: Tránh nhồi nhét quá nhiều logic hoặc quá nhiều trách nhiệm vào một container. Tuân thủ nguyên tắc một trách nhiệm, ưu tiên sự đơn giản khi có thể.
- Bỏ qua cấu hình mạng rõ ràng: Hãy định nghĩa mạng tùy chỉnh trong Compose thay vì phụ thuộc vào hành vi mặc định. Điều này cho phép kiểm soát tốt hơn giao tiếp giữa dịch vụ, giảm xung đột cổng và cải thiện ranh giới bảo mật.
Bằng cách áp dụng các thực hành này, quy trình làm việc dựa trên Compose của bạn sẽ vững chắc hơn, an toàn hơn và dễ bảo trì hơn trong môi trường cộng tác hoặc đang phát triển.
Kết luận
Docker Compose đơn giản hóa đáng kể việc xây dựng, quản lý và vận hành các ứng dụng nhiều container cho nhà phát triển. Định nghĩa rõ ràng dựa trên YAML, điều phối dễ dàng và khả năng mở rộng trực quan khiến nó trở nên vô giá cho các kịch bản phát triển cục bộ và kiến trúc triển khai đơn giản. Mặc dù các bộ điều phối nâng cao như Docker Swarm và Kubernetes phù hợp hơn với khối lượng công việc sản xuất quy mô lớn, Compose vẫn là điểm khởi đầu thiết yếu để hiểu các nguyên lý điều phối container và cải thiện quy trình làm việc của nhà phát triển.
Khám phá các khóa học Docker của chúng tôi để học:
Câu hỏi thường gặp về Docker Compose
Docker Compose khác gì so với Docker Swarm hoặc Kubernetes?
Docker Compose lý tưởng cho phát triển cục bộ và kiểm thử quy mô nhỏ. Với điều phối cấp sản xuất có tính năng như tự mở rộng và tự phục hồi, Docker Swarm và Kubernetes phù hợp hơn.
Docker Compose có quản lý phụ thuộc giữa services không?
Có, Compose cho phép bạn định nghĩa phụ thuộc với chỉ thị depends_on. Các script hỗ trợ bên ngoài như wait-for-it có thể dùng để kiểm soát chính xác hơn, chẳng hạn chờ cơ sở dữ liệu sẵn sàng.
Làm thế nào để quản lý nhiều môi trường bằng Docker Compose?
Bạn có thể dùng nhiều tệp Compose (ví dụ, docker-compose.yml và docker-compose.prod.yml) và ghi đè cấu hình theo môi trường bằng cờ -f khi chạy lệnh.
Docker Compose có hỗ trợ health check và chính sách khởi động lại không?
Có, Docker Compose hỗ trợ health check cho container và chính sách khởi động lại, cho phép bạn tăng độ bền vững của dịch vụ trong phát triển và kiểm thử.
