
Tóm tắt nhanh
- Sử dụng YAML anchors để tái sử dụng cấu hình giữa các services
- Pin image versions để đảm bảo reproducibility
- Tách biệt .env file riêng cho mỗi môi trường
- Sử dụng health checks để theo dõi trạng thái container
- Áp dụng restart policies phù hợp với từng service
Docker Compose là gì?
Docker Compose là một công cụ cho phép bạn định nghĩa và chạy multi-container Docker applications với một file YAML duy nhất. Thay vì phải chạy từng container bằng tay với các câu lệnh dài dòng, bạn chỉ cần viết cấu hình một lần và Docker Compose sẽ xử lý tất cả.
Bạn có đang gặp tình trạng “works on my machine”? Khi mà ứng dụng chạy tốt trên máy dev nhưng lại không hoạt động ở máy khác? Đây là lý do Docker Compose trở nên quan trọng — nó đảm bảo môi trường consistent giữa các máy [1].
Trong bài viết này, mình sẽ chia sẻ 10 best practices để sử dụng Docker Compose hiệu quả nhất trong năm 2026. Cùng bắt đầu nhé!

Tổ chức cấu trúc Compose file
Mỗi docker-compose.yml nên được đặt trong thư mục riêng cùng với file .env và các config liên quan. Cách này giúp bạn dễ dàng quản lý và di chuyển toàn bộ stack [3].
Thay vì để tất cả trong một thư mục lộn xộn, hãy tổ chức theo cấu trúc:
my-app/ ├── docker-compose.yml ├── .env ├── config/ │ └── nginx.conf └── README.md
Cách này giúp team members dễ dàng hiểu cấu trúc project và tìm file cần thiết. Đây là điều bạn nên áp dụng từ ngay hôm nay!
Sử dụng YAML Anchors để tái sử dụng cấu hình
YAML anchors cho phép bạn định nghĩa một cấu hình chung và tái sử dụng nó cho nhiều services, giúp giảm duplicate code. Đây là tính năng mạnh mẽ của YAML mà ít người biết [1].
Ví dụ, thay vì lặp lại cùng một cấu hình cho nhiều services:
version: '3.9'
services:
web:
&service_default
image: nginx:alpine
init: true
restart: always
api:
<<: *service_default
image: node:20-alpine
worker:
<<: *service_default
image: python:3.11-slim
Thú vị nhỉ! Chỉ với vài dòng code, bạn đã có thể áp dụng cùng một cấu hình cho 3 services khác nhau. Điều này giúp maintain code dễ dàng hơn rất nhiều.

Pin Image Versions để đảm bảo reproducibility
Luôn pin cụ thể image version thay vì dùng tag “latest” — đây là một trong những best practices quan trọng nhất [4].
Khi bạn dùng nginx:latest, container của bạn có thể thay đổi bất cứ lúc nào khi image được cập nhật. Điều này dẫn đến tình trạng không thể reproduce được môi trường.
Cách làm đúng:
services:
web:
image: nginx:1.25-alpine # Pin cụ thể phiên bản
# Hoặc dùng digest cho độ chính xác cao hơn
image: nginx@sha256:abc123...
Mình khuyên bạn nên dùng specific tags như 1.25-alpine thay vì latest. Đây là cách đơn giản nhưng hiệu quả để tránh bugs không mong muốn.
Sử dụng Health Checks để theo dõi trạng thái
Health checks cho phép Docker Compose theo dõi xem container của bạn có đang hoạt động đúng hay không. Nếu health check fails, Docker sẽ tự động restart container [2].
Ví dụ với PostgreSQL:
services:
db:
image: postgres:15-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
Điều tuyệt vời là các services khác có thể depend_on container này và chỉ start khi database ready! Bạn sẽ không còn gặp lỗi “connection refused” nữa.

Restart Policies phù hợp cho từng Service
Docker Compose cung cấp nhiều restart policies: no, always, on-failure, và unless-stopped. Việc chọn đúng policy giúp ứng dụng của bạn tự phục hồi khi gặp sự cố.
Gợi ý của mình:
- always: Cho các services cần chạy liên tục như web server, database
- on-failure: Cho workers hoặc batch jobs, restart khi có lỗi
- unless-stopped: Cho development, giữ nguyên trạng thái khi reboot
services:
web:
restart: always
worker:
restart: on-failure
db:
restart: always
Đừng quên rằng restart policy chỉ hoạt động khi container được quản lý bởi Docker Compose, không phải khi bạn chạy thủ công!
Quản lý Environment Files cho từng môi trường
Sử dụng nhiều .env files cho development, staging, production để quản lý cấu hình dễ dàng. Đây là cách tiếp cận professional mà nhiều teams áp dụng [3].
Cấu trúc đề xuất:
.env # Default, chung cho tất cả .env.development # Override cho dev .env.production # Override cho prod
Trong docker-compose.yml:
services:
api:
env_file:
- .env
- .env.${ENV:-development}
Cách này giúp bạn dễ dàng switch giữa các môi trường mà không cần sửa code. Thật tiện lợi phải không?
Networking giữa các Services
Docker Compose tự động tạo một default network cho tất cả services trong cùng file. Các services có thể giao tiếp với nhau qua service name như hostname.
services:
web:
image: nginx
ports:
- "80:80"
api:
build: ./api
# Không cần specify network, tự động connect
# web có thể gọi api qua: http://api:3000
Tuy nhiên, với production, bạn nên tạo networks riêng biệt để tăng security:
networks:
frontend:
backend:
internal: true # Không access từ bên ngoài
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
Đây là cách bạn có thể bảo vệ database khỏi being exposed ra ngoài!

Volume Mounts tối ưu cho Development và Production
Chọn đúng loại volume mount giúp tăng performance và đảm bảo data persistence. Có 2 loại chính: bind mounts và named volumes.
Cho development:
services:
web:
volumes:
- ./src:/app/src:ro # Bind mount, thay đổi ngay lập tức
Cho production:
services:
db:
volumes:
- db-data:/var/lib/postgresql/data # Named volumes
volumes:
db-data:
Mình khuyên bạn nên dùng named volumes cho production vì chúng có performance tốt hơn và dễ quản lý hơn. Còn bind mounts thì perfect cho development workflow!
Security Best Practices trong Docker Compose
Bảo mật là yếu tố không thể bỏ qua. Dưới đây là các best practices quan trọng [10]:
- Không chạy container với quyền root: Dùng
user: "1000:1000" - Giới hạn capabilities: Chỉ cấp những capabilities cần thiết
- Dùng security options:
security_opt:vàread_only: true - Scan images thường xuyên: Dùng Trivy hoặc similar tools [8]
- Update images regularly: Theo dõi security advisories
services:
web:
security_opt:
- no-new-privileges:true
read_only: true
user: "1000:1000"
tmpfs:
- /tmp
- /run
Nhớ rằng, security không phải là một lần setup xong là xong. Bạn cần regularly review và update security measures!
Kết luận
Docker Compose là công cụ mạnh mẽ giúp quản lý multi-container applications một cách hiệu quả. Bằng cách áp dụng 10 best practices trên, bạn sẽ có một hệ thống stable, secure, và dễ maintain.
Những điểm quan trọng cần nhớ:
- Tổ chức cấu trúc file rõ ràng
- Pin image versions
- Sử dụng health checks
- Chọn restart policy phù hợp
- Quản lý environment files đúng cách
- Áp dụng security best practices
Bạn đã áp dụng những best practices nào trong project của mình? Chia sẻ kinh nghiệm nhé!
Nguồn tham khảo
- Docker compose best practices every developer should know
- Kubernetes 2026 Complete Guide
- Docker Compose Best Practices for Enhanced System Resilience
- Beginner-Friendly Docker Best Practices In 2026
- Docker Best Practices 2026
- Mastering Docker Compose: Advanced Patterns
- How to Optimize Docker on Linux Server in 2026
- What Is Containerization? A Complete 2026 Guide
- 9 Docker Best Practices You Should Know
- Container Security Best Practices: An Enterprise Guide for 2026
Các câu hỏi thường gặp
Docker Compose khác gì với Dockerfile?
Dockerfile định nghĩa cách build một image, còn Docker Compose định nghĩa cách chạy nhiều containers cùng nhau. Bạn có thể dùng cả hai: Dockerfile để build image, Compose để orchestrate containers.
Tôi nên dùng Docker Compose hay Kubernetes?
Docker Compose phù hợp cho development và small deployments. Kubernetes dành cho production-scale applications với high availability requirements. Nhiều teams dùng Compose cho local dev và Kubernetes cho production.
Làm sao để debug khi container không chạy?
Dùng docker-compose logs [service_name] để xem logs. Hoặc docker-compose up --build --verbose để chạy với debug mode. Kiểm tra health check configuration nếu container bị restart liên tục.
Có nên dùng “latest” tag cho Docker images?
Không nên! Luôn pin specific versions (như nginx:1.25-alpine) để đảm bảo reproducibility. Dùng “latest” có thể khiến ứng dụng behave khác nhau qua thời gian khi image được update.