Skip to content
VDS · Docker và container

Docker Compose: nhiều dịch vụ với một lệnh

Cách mô tả một gói gồm ứng dụng, cơ sở dữ liệu và máy chủ web trong một tệp, khởi động bằng một lệnh và cập nhật mà không cần build lại thủ công.

Cập nhật 23 tháng 8, 2026

Bạn có thể khởi chạy một dịch vụ duy nhất bằng một lệnh docker run dài. Hai dịch vụ cần thấy nhau — cách đó không còn hiệu quả nữa: bạn sẽ quên các tham số vào ngày hôm sau. Compose chuyển toàn bộ phần mô tả vào một tệp mà bạn có thể đọc, chỉnh sửa và lưu trong kho lưu trữ.

Ví dụ tối giản

Thư mục /opt/myapp, với compose.yaml bên trong:

services:
  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      retries: 5

  app:
    image: ghcr.io/example/app:1.4.2
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/app
    ports:
      - "127.0.0.1:8080:8080"

volumes:
  db-data:

Bên cạnh đó là tệp .env:

DB_PASSWORD=long-random-password
chmod 600 .env
docker compose up -d
docker compose ps
docker compose logs -f app

Những điều quan trọng ở đây

  • Tên thay vì địa chỉ. Ứng dụng kết nối tới cơ sở dữ liệu bằng tên db — Compose tạo một mạng dùng chung nơi tên dịch vụ được phân giải tự động. Bạn không cần công khai cổng của cơ sở dữ liệu ra bên ngoài, và cũng không nên làm vậy.
  • restart: unless-stopped. Nếu không có nó, sẽ không có gì khởi động lại sau khi máy khởi động lại.
  • depends_on với health check. depends_on thông thường chỉ chờ container khởi động, chứ không chờ cơ sở dữ liệu sẵn sàng nhận kết nối. Ứng dụng khởi động sớm hơn và gặp sự cố.
  • Phiên bản image chính xác. postgres:17, không phải postgres:latest. Với latest, một ngày nào đó lệnh pull tiếp theo sẽ mang về một phiên bản major không mở được dữ liệu cũ.
  • Công khai trên 127.0.0.1. Chỉ mở cổng ra bên ngoài thông qua một web server có chứng chỉ.

Các lệnh thường dùng

docker compose up -d          # bring up or apply changes
docker compose down           # stop and remove containers (volumes intact)
docker compose down -v        # ...and remove volumes too
docker compose restart app    # restart one service
docker compose exec app sh    # go inside
docker compose pull && docker compose up -d   # update images
docker compose config         # show final file with substitutions

docker compose config là cách tốt nhất để kiểm tra tệp trước khi khởi chạy: nó sẽ hiển thị các biến đã được thay bằng gì và liệu có bị mất thụt lề hay không.

docker compose down -v xóa các volume cùng với cơ sở dữ liệu. Thao tác này không thể hoàn tác. Trước bất kỳ thao tác nào với -v, hãy đảm bảo bạn có bản sao — xem sao lưu.

Tệp môi trường

Sẽ rất tiện khi tách cùng một stack cho kiểm thử và production bằng các overlay:

docker compose -f compose.yaml -f compose.prod.yaml up -d

Tệp thứ hai chỉ ghi đè những điểm khác biệt: giới hạn bộ nhớ, cổng được công khai và mức log.

Những lỗi thường gặp

  • Bí mật trong compose.yaml được lưu trong kho lưu trữ. Hãy giữ chúng trong .env với quyền 600 và đừng commit tệp đó.
  • Trộn lẫn docker-compose và docker compose. Phiên bản v1 cũ không hiểu một số cú pháp và lưu các dự án dưới những tên khác nhau. Hãy cài plugin — xem Cài đặt Docker.
  • Dữ liệu trong container thay vì trong volume. Sau docker compose down, nó sẽ biến mất. Xem volume.
  • Không có giới hạn bộ nhớ. Một dịch vụ ăn hết bộ nhớ của máy, và kernel sẽ kill các dịch vụ bên cạnh. Xem giới hạn tài nguyên.