# Docker Compose 2026: Ứng dụng Multi-Container, Networking và Câu hỏi Phỏng vấn DevOps > Hướng dẫn Docker Compose cho ứng dụng multi-container với networking, volumes và deployment production. Bao gồm câu hỏi phỏng vấn DevOps. - Published: 2026-08-03 - Updated: 2026-08-03 - Author: SharpSkill - Reading time: 5 min --- Docker Compose vẫn là công cụ hàng đầu để định nghĩa và chạy các ứng dụng Docker multi-container trong năm 2026. Dù là orchestrating stack development local hay chuẩn bị cho phỏng vấn DevOps, hiểu về Compose networking, service dependencies và các pattern production phân biệt engineer junior với các practitioner senior. > **Điểm Chính** > > Docker Compose sử dụng định dạng YAML declarative để định nghĩa services, networks và volumes trong một file duy nhất. Chạy `docker compose up` sẽ khởi động toàn bộ application stack với networking cô lập và storage persistent. ## Hiểu Kiến trúc Docker Compose Docker Compose hoạt động dựa trên nguyên tắc đơn giản: định nghĩa các services của ứng dụng trong file `compose.yaml` (quy ước đặt tên hiện đại thay thế `docker-compose.yml`), và Compose xử lý việc tạo container, networking và quản lý lifecycle. [Đặc tả Docker Compose](https://docs.docker.com/compose/compose-file/) định nghĩa ba khái niệm cốt lõi: - **Services**: Cấu hình container bao gồm image, build context, environment variables và resource limits - **Networks**: Các kênh giao tiếp cô lập giữa services - **Volumes**: Storage dữ liệu persistent tồn tại sau khi container restart ```yaml # compose.yaml services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://db:5432/app depends_on: db: condition: service_healthy networks: - backend db: image: postgres:16 volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_DB=app - POSTGRES_PASSWORD_FILE=/run/secrets/db_password secrets: - db_password healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 networks: - backend networks: backend: driver: bridge volumes: postgres_data: secrets: db_password: file: ./secrets/db_password.txt ``` Cấu hình này minh họa nhiều pattern production-ready: health checks cho dependency ordering, Docker secrets cho dữ liệu nhạy cảm, named volumes cho persistence, và định nghĩa network rõ ràng. ## Đi sâu vào Docker Compose Networking Mặc định, Compose tạo một network duy nhất cho ứng dụng. Tất cả services tham gia network này và có thể liên lạc với nhau bằng tên service làm hostname. Hiểu mô hình networking này là nền tảng cho [migration sang Kubernetes](/blog/devops/kubernetes-deploying-first-application) sau này. ```yaml # compose.yaml services: frontend: build: ./frontend ports: - "80:80" networks: - frontend-net - backend-net api: build: ./api networks: - backend-net cache: image: redis:7-alpine networks: - backend-net db: image: postgres:16 networks: - backend-net networks: frontend-net: driver: bridge backend-net: driver: bridge internal: true ``` Flag `internal: true` ngăn backend network truy cập internet bên ngoài. Service frontend kết nối cả hai networks, đóng vai trò là điểm vào duy nhất. Phân đoạn network này phản ánh các thực hành bảo mật production. > **DNS Resolution** > > DNS server tích hợp của Docker tự động resolve tên service. Service `api` có thể kết nối database tại `db:5432` mà không cần cấu hình IP thủ công. ## Multi-Stage Builds với Compose Image production nên tối giản. Multi-stage builds kết hợp với Compose profiles cho phép cấu hình khác nhau cho development và production. ```dockerfile # api/Dockerfile # Stage 1: Build FROM node:22-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:22-alpine AS production WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ USER node EXPOSE 3000 CMD ["node", "dist/index.js"] # Stage 3: Development FROM node:22-alpine AS development WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . USER node CMD ["npm", "run", "dev"] ``` ```yaml # compose.yaml services: api: build: context: ./api target: ${BUILD_TARGET:-production} volumes: - ${API_VOLUMES:-./api/dist:/app/dist:ro} profiles: - ${COMPOSE_PROFILES:-prod} ``` Chạy `BUILD_TARGET=development COMPOSE_PROFILES=dev docker compose up` khởi động cấu hình development với hot reload. ## Service Dependencies và Health Checks Directive `depends_on` kiểm soát thứ tự startup, nhưng container được khởi động không có nghĩa là service đã sẵn sàng. Health checks giải quyết vấn đề timing này—pattern thường được hỏi trong [phỏng vấn DevOps](/blog/devops/essential-devops-interview-questions). ```yaml # compose.yaml services: api: build: ./api depends_on: db: condition: service_healthy cache: condition: service_started migrations: condition: service_completed_successfully migrations: build: ./api command: npm run migrate depends_on: db: condition: service_healthy db: image: postgres:16 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 3s retries: 5 start_period: 10s cache: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 3 ``` Ba điều kiện dependency có sẵn: - `service_started`: Mặc định, container đã được khởi động - `service_healthy`: Health check thành công - `service_completed_successfully`: Container exit với code 0 (cho init containers) ## Docker Compose cho Development Local Môi trường development được hưởng lợi từ bind mounts, environment overrides và debugging tools. File `compose.override.yaml` tự động được merge với `compose.yaml`. ```yaml # compose.yaml (cấu hình cơ bản) services: api: build: ./api environment: - NODE_ENV=production db: image: postgres:16 ``` ```yaml # compose.override.yaml (override cho development) services: api: build: target: development volumes: - ./api:/app - /app/node_modules environment: - NODE_ENV=development - DEBUG=app:* ports: - "9229:9229" db: ports: - "5432:5432" ``` Anonymous volume `/app/node_modules` ngăn node_modules của host ghi đè lên dependencies đã cài trong container. ## Các Pattern Deployment Production Docker Compose phù hợp cho deployment production single-host. Để orchestration multi-host, [Kubernetes với Helm](/blog/devops/kubernetes-helm-charts-2026-packaging-deployment-interview-questions) cung cấp khả năng scaling tốt hơn, nhưng Compose vẫn khả thi cho các ứng dụng nhỏ. ```yaml # compose.prod.yaml services: api: image: registry.example.com/api:${VERSION:-latest} deploy: replicas: 3 resources: limits: cpus: "0.5" memory: 512M reservations: cpus: "0.25" memory: 256M restart_policy: condition: on-failure delay: 5s max_attempts: 3 logging: driver: json-file options: max-size: "10m" max-file: "3" nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./certs:/etc/nginx/certs:ro depends_on: - api ``` Key `deploy` cấu hình resource limits, số lượng replicas và restart policies. Chạy `docker compose -f compose.prod.yaml up -d` khởi động stack production trong chế độ detached. ## Environment Variables và Quản lý Secrets Cấu hình nhạy cảm đòi hỏi xử lý đúng cách. Docker Compose hỗ trợ nhiều phương pháp, từ file `.env` đến Docker secrets. ```bash # .env POSTGRES_PASSWORD=dev_password_only API_SECRET_KEY=local_dev_key ``` ```yaml # compose.yaml services: api: environment: - API_SECRET_KEY # Kế thừa từ shell hoặc .env - DATABASE_URL=postgres://user:${POSTGRES_PASSWORD}@db:5432/app env_file: - ./config/api.env ``` Cho production, Docker secrets cung cấp bảo mật tốt hơn bằng cách mount dữ liệu nhạy cảm dưới dạng file thay vì environment variables: ```yaml # compose.prod.yaml services: api: secrets: - api_key - db_password environment: - API_KEY_FILE=/run/secrets/api_key secrets: api_key: external: true db_password: file: ./secrets/db_password.txt ``` > **Lưu ý Bảo mật** > > Không bao giờ commit file `.env` chứa secrets production vào version control. Sử dụng quản lý secret bên ngoài như HashiCorp Vault hoặc các giải pháp cloud provider cho deployment production. ## Các Câu hỏi Phỏng vấn DevOps Phổ biến về Docker Compose Người phỏng vấn kiểm tra sự hiểu biết về các khái niệm Compose thông qua các kịch bản thực tế. Những câu hỏi này thường xuất hiện trong phỏng vấn DevOps và platform engineering. **H: Các container trong Compose network giao tiếp với nhau như thế nào?** Docker tạo một dedicated bridge network cho mỗi Compose project. Các services giao tiếp bằng tên service làm hostname. DNS server tích hợp resolve các tên này thành địa chỉ IP container. Traffic bên ngoài chỉ có thể tiếp cận services thông qua các port được publish rõ ràng. **H: Điều gì xảy ra khi chạy `docker compose up` với các container đang tồn tại?** Compose so sánh cấu hình hiện tại với các container đang chạy. Các services không thay đổi tiếp tục chạy. Các services đã sửa đổi được tạo lại với cài đặt mới. Các services mới được khởi động mới. Các services bị xóa được dừng và xóa bỏ. **H: Cách xử lý database migrations trong Compose?** Có hai pattern. Thứ nhất, sử dụng init container với dependency `service_completed_successfully`: ```yaml services: migrate: image: api:latest command: npm run migrate depends_on: db: condition: service_healthy api: depends_on: migrate: condition: service_completed_successfully ``` Thứ hai, bao gồm logic migration trong script startup của ứng dụng, kiểm tra và áp dụng các migration pending trước khi nhận traffic. **H: Sự khác biệt giữa volumes và bind mounts là gì?** Named volumes được Docker quản lý, lưu trữ tại `/var/lib/docker/volumes`, và portable giữa các host. Bind mounts map trực tiếp thư mục host vào container, hữu ích cho development nhưng phụ thuộc môi trường. Volumes hỗ trợ drivers cho remote storage như NFS hoặc cloud block storage. **H: Sự khác biệt giữa `docker-compose` và `docker compose` là gì?** `docker-compose` có dấu gạch ngang là tool standalone V1 dựa trên Python, hiện đã deprecated. `docker compose` có dấu cách là implementation V2 dựa trên Go được tích hợp vào Docker CLI. V2 nhanh hơn, hỗ trợ đầy đủ Compose Specification, và đang được phát triển tích cực. ## Debug Ứng dụng Compose Troubleshooting các ứng dụng containerized đòi hỏi các kỹ thuật cụ thể. Các lệnh này tiết lộ những gì đang xảy ra bên trong stack Compose: ```bash # Xem logs từ tất cả services docker compose logs -f # Logs từ service cụ thể với timestamps docker compose logs -f --timestamps api # Thực thi command trong container đang chạy docker compose exec api sh # Chạy command một lần (khởi động container mới) docker compose run --rm api npm test # Xem sử dụng resource docker compose top docker stats # Inspect cấu hình network docker network inspect project_backend # Validate compose file docker compose config ``` Lệnh `docker compose config` merge tất cả compose files và hiển thị cấu hình cuối cùng—vô giá cho việc debug các vấn đề interpolation biến. ## Kết luận - Docker Compose định nghĩa các ứng dụng multi-container trong một file YAML duy nhất với services, networks và volumes - Các services giao tiếp qua DNS sử dụng tên service làm hostname trong default bridge network - Health checks với điều kiện `service_healthy` đảm bảo thứ tự startup đúng - Sử dụng `compose.override.yaml` cho cài đặt development-specific như bind mounts và debug ports - Deployment production được hưởng lợi từ resource limits, restart policies, và Docker secrets cho dữ liệu nhạy cảm - CLI `docker compose` (V2) thay thế `docker-compose` (V1) deprecated với hiệu năng và tính năng tốt hơn --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/vi/blog/devops/docker-compose-2026-multi-container-networking-devops-interview