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.

Docker Compose 2026: Ứng dụng Multi-Container, Networking và Câu hỏi Phỏng vấn DevOps

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 đị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 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.

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)

Sẵn sàng chinh phục phỏng vấn DevOps?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

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 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-composedocker 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

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Chia sẻ

Bài viết liên quan