Docker Compose 完全指南

深入理解 Docker Compose 的配置、參數說明、多容器編排與實際應用


目錄


Docker Compose 基礎

什麼是 Docker Compose?

Docker Compose 是一個多容器編排工具,用單一配置檔(docker-compose.yml)定義和管理多個相關的容器。

為什麼需要 Docker Compose?

沒有 Compose(手動管理)

# 建立網路
docker network create my-network

# 啟動資料庫
docker run -d \
  --name db \
  --network my-network \
  -e POSTGRES_PASSWORD=secret \
  -v db-data:/var/lib/postgresql/data \
  postgres

# 啟動後端
docker run -d \
  --name api \
  --network my-network \
  -e DATABASE_URL=postgresql://db:5432/mydb \
  -p 8080:8080 \
  myapi

# 啟動前端
docker run -d \
  --name web \
  --network my-network \
  -p 80:80 \
  nginx

使用 Compose(簡化管理)

# docker-compose.yml
version: '3.8'

services:
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - db-data:/var/lib/postgresql/data

  api:
    image: myapi
    environment:
      DATABASE_URL: postgresql://db:5432/mydb
    ports:
      - "8080:8080"
    depends_on:
      - db

  web:
    image: nginx
    ports:
      - "80:80"

volumes:
  db-data:

啟動只需一個指令

docker-compose up -d

docker-compose.yml 結構

基本結構

version: '3.8'          # Compose 檔案版本

services:               # 定義服務(容器)
  service1:
    # 服務配置
  service2:
    # 服務配置

networks:               # 定義網路(選擇性)
  network1:
    # 網路配置

volumes:                # 定義資料卷(選擇性)
  volume1:
    # 資料卷配置

configs:                # 定義配置(選擇性)
  config1:
    # 配置內容

secrets:                # 定義機密資料(選擇性)
  secret1:
    # 機密配置

版本說明

版本 最低 Docker 版本 說明
3.8 19.03.0+ 推薦使用
3.7 18.06.0+ 穩定版本
3.0 1.13.0+ 基本版本
2.x 已棄用 舊版本

建議:使用 version: '3.8'


Services 服務配置

1. image - 指定映像

services:
  web:
    image: nginx:1.21              # 使用官方映像

  api:
    image: myregistry.com/myapi:v1 # 使用私有倉庫

  app:
    image: myapp:latest            # 使用本地映像

2. build - 建構映像

基本用法

services:
  app:
    build: .                       # 使用當前目錄的 Dockerfile

指定 Dockerfile

services:
  app:
    build:
      context: ./app               # 建構上下文目錄
      dockerfile: Dockerfile.dev   # 指定 Dockerfile

建構參數

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:                        # 建構時的參數
        - NODE_ENV=production
        - API_KEY=${API_KEY}
      target: production           # 多階段建構的目標
      cache_from:                  # 快取來源
        - myapp:latest

同時使用 build 和 image

services:
  app:
    build: .
    image: myapp:v1                # 建構後的映像名稱

3. container_name - 容器名稱

services:
  db:
    image: postgres
    container_name: my-postgres-db # 自訂容器名稱

注意

  • 如果不指定,Docker Compose 會自動產生名稱:<專案名>_<服務名>_<序號>
  • 例如:myproject_db_1

4. ports - Port 映射

語法

ports:
  - "宿主機port:容器port"
  - "宿主機IP:宿主機port:容器port"

範例

services:
  web:
    image: nginx
    ports:
      - "80:80"                    # 映射到宿主機的 80 port
      - "443:443"                  # 映射多個 port
      - "8080:80"                  # 宿主機 8080 → 容器 80
      - "127.0.0.1:8080:80"        # 只綁定到 localhost
      - "3000-3005:3000-3005"      # port 範圍映射

短語法 vs 長語法

# 短語法
ports:
  - "8080:80"

# 長語法(更詳細)
ports:
  - target: 80                     # 容器內的 port
    published: 8080                # 宿主機的 port
    protocol: tcp                  # tcp 或 udp
    mode: host                     # host 或 ingress

5. expose - 暴露 Port(內部使用)

services:
  api:
    image: myapi
    expose:
      - "8080"                     # 只對其他容器暴露,不對外

expose vs ports

  • expose:只在容器間可見,不映射到宿主機
  • ports:映射到宿主機,外部可存取

6. environment - 環境變數

方式 1:直接定義

services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb

方式 2:陣列格式

services:
  db:
    image: postgres
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=mydb

方式 3:從宿主機取得

services:
  api:
    image: myapi
    environment:
      - DATABASE_URL=${DATABASE_URL}  # 從 .env 或宿主機環境變數
      - API_KEY                        # 使用宿主機的 API_KEY 變數

7. env_file - 環境變數檔案

單一檔案

services:
  api:
    image: myapi
    env_file: .env                 # 從 .env 檔案載入

多個檔案

services:
  api:
    image: myapi
    env_file:
      - .env                       # 基本環境變數
      - .env.local                 # 本地覆寫
      - .env.production            # 生產環境

.env 檔案範例

# .env
DATABASE_URL=postgresql://localhost:5432/mydb
REDIS_URL=redis://localhost:6379
API_KEY=your-api-key-here

8. volumes - 資料卷掛載

語法

volumes:
  - "宿主機路徑:容器路徑"
  - "宿主機路徑:容器路徑:選項"
  - "具名資料卷:容器路徑"

範例

services:
  db:
    image: postgres
    volumes:
      # 具名資料卷(推薦)
      - db-data:/var/lib/postgresql/data

      # 綁定掛載(開發環境)
      - ./app:/app

      # 唯讀掛載
      - ./config:/config:ro

      # 指定權限
      - ./data:/data:rw

volumes:
  db-data:                         # 定義具名資料卷

長語法

services:
  web:
    image: nginx
    volumes:
      - type: volume               # volume, bind, tmpfs
        source: web-data           # 資料卷名稱或宿主機路徑
        target: /data              # 容器內路徑
        read_only: false           # 是否唯讀
        volume:
          nocopy: false            # 是否複製容器中的資料

9. networks - 網路配置

連接到網路

services:
  web:
    image: nginx
    networks:
      - frontend
      - backend

networks:
  frontend:
  backend:

指定 IP

services:
  web:
    image: nginx
    networks:
      frontend:
        ipv4_address: 172.20.0.10

networks:
  frontend:
    ipam:
      config:
        - subnet: 172.20.0.0/16

網路別名

services:
  db:
    image: postgres
    networks:
      backend:
        aliases:
          - database
          - postgres-db

10. depends_on - 依賴關係

基本用法

services:
  web:
    image: nginx
    depends_on:
      - api                        # 等待 api 啟動後才啟動 web

  api:
    image: myapi
    depends_on:
      - db                         # 等待 db 啟動後才啟動 api

  db:
    image: postgres

啟動順序:db → api → web

長語法(等待條件)

services:
  web:
    image: nginx
    depends_on:
      api:
        condition: service_healthy # 等待服務健康檢查通過

  api:
    image: myapi
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

注意depends_on 只控制啟動順序,不等待服務「完全準備好」。


11. command - 覆寫預設指令

services:
  app:
    image: node:14
    command: npm start             # 覆寫 Dockerfile 的 CMD

  worker:
    image: myapp
    command: ["python", "worker.py"] # 陣列格式

  dev:
    image: myapp
    command: >
      npm run dev
      --hot-reload                 # 多行指令

12. entrypoint - 覆寫進入點

services:
  app:
    image: myapp
    entrypoint: /app/entrypoint.sh

  debug:
    image: myapp
    entrypoint: ["sh", "-c"]
    command: ["sleep 3600"]        # 保持容器運行以便除錯

13. restart - 重啟策略

services:
  web:
    image: nginx
    restart: always                # 總是重啟

  api:
    image: myapi
    restart: unless-stopped        # 除非手動停止,否則重啟

  worker:
    image: myworker
    restart: on-failure            # 只在失敗時重啟

  test:
    image: test
    restart: "no"                  # 不重啟(預設)
策略 說明
no 不重啟(預設)
always 總是重啟
on-failure 只在失敗時重啟
unless-stopped 除非手動停止,否則重啟

14. healthcheck - 健康檢查

services:
  api:
    image: myapi
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s                # 每 30 秒檢查一次
      timeout: 10s                 # 超時時間
      retries: 3                   # 重試次數
      start_period: 40s            # 啟動寬限期

常見測試指令

# HTTP 健康檢查
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]

# PostgreSQL
test: ["CMD-SHELL", "pg_isready -U postgres"]

# MySQL
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]

# Redis
test: ["CMD", "redis-cli", "ping"]

# 自訂腳本
test: ["CMD", "/app/healthcheck.sh"]

# 停用健康檢查
test: ["NONE"]

15. labels - 標籤

services:
  web:
    image: nginx
    labels:
      - "com.example.description=Web Server"
      - "com.example.version=1.0"
      - "traefik.enable=true"      # Traefik 反向代理

16. logging - 日誌配置

services:
  web:
    image: nginx
    logging:
      driver: json-file            # 日誌驅動
      options:
        max-size: "10m"            # 單一日誌檔案最大 10MB
        max-file: "3"              # 保留 3 個日誌檔案

日誌驅動選項

  • json-file(預設)
  • syslog
  • journald
  • gelf
  • fluentd
  • none(停用日誌)

17. deploy - 部署配置(Swarm)

services:
  web:
    image: nginx
    deploy:
      replicas: 3                  # 執行 3 個副本
      update_config:
        parallelism: 1             # 一次更新 1 個
        delay: 10s                 # 更新間隔
      restart_policy:
        condition: on-failure
        max_attempts: 3
      resources:
        limits:
          cpus: '0.5'              # CPU 限制
          memory: 512M             # 記憶體限制
        reservations:
          cpus: '0.25'
          memory: 256M

注意deploy 只在 Docker Swarm 模式下有效。


18. extra_hosts - 額外的 hosts

services:
  app:
    image: myapp
    extra_hosts:
      - "api.example.com:192.168.1.100"
      - "db.example.com:192.168.1.200"

相當於在容器的 /etc/hosts 中添加:

192.168.1.100  api.example.com
192.168.1.200  db.example.com

19. dns - DNS 設定

services:
  app:
    image: myapp
    dns:
      - 8.8.8.8                    # Google DNS
      - 8.8.4.4

  app2:
    image: myapp
    dns_search:                    # DNS 搜尋域
      - example.com

20. security_opt - 安全選項

services:
  app:
    image: myapp
    security_opt:
      - no-new-privileges:true     # 禁止提權
      - seccomp:unconfined         # 停用 seccomp

21. user - 執行使用者

services:
  app:
    image: myapp
    user: "1000:1000"              # UID:GID

  nginx:
    image: nginx
    user: nginx                    # 使用者名稱

22. working_dir - 工作目錄

services:
  app:
    image: node:14
    working_dir: /app
    command: npm start

23. stdin_opentty - 互動模式

services:
  app:
    image: ubuntu
    stdin_open: true               # 等同於 docker run -i
    tty: true                      # 等同於 docker run -t
    command: bash

24. privileged - 特權模式

services:
  docker:
    image: docker:dind
    privileged: true               # 允許容器存取宿主機所有設備

⚠️ 警告:特權模式有安全風險,只在必要時使用。


25. cap_addcap_drop - Linux 能力

services:
  app:
    image: myapp
    cap_add:
      - NET_ADMIN                  # 添加網路管理能力
      - SYS_TIME                   # 添加時間設定能力
    cap_drop:
      - ALL                        # 移除所有能力(然後再添加需要的)

Networks 網路配置

預設行為

# 不指定 networks 時,Compose 自動建立 <專案名>_default 網路
services:
  web:
    image: nginx
  api:
    image: myapi

自訂網路

services:
  web:
    image: nginx
    networks:
      - frontend

  api:
    image: myapi
    networks:
      - frontend
      - backend

  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

網路驅動

networks:
  # Bridge 網路(預設)
  app-network:
    driver: bridge

  # Host 網路
  host-network:
    driver: host

  # Overlay 網路(Swarm)
  overlay-network:
    driver: overlay

  # Macvlan 網路
  macvlan-network:
    driver: macvlan
    driver_opts:
      parent: eth0

指定子網路

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1

內部網路(禁止連外)

networks:
  internal-network:
    driver: bridge
    internal: true                 # 無法存取外部網路

使用已存在的網路

networks:
  existing-network:
    external: true                 # 使用外部已建立的網路
    name: my-pre-existing-network  # 外部網路的實際名稱

Volumes 資料卷配置

具名資料卷

services:
  db:
    image: postgres
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:                         # 定義具名資料卷

資料卷驅動

volumes:
  data:
    driver: local                  # 本地驅動(預設)

  nfs-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.100,rw
      device: ":/path/to/share"

外部資料卷

volumes:
  existing-volume:
    external: true                 # 使用外部已建立的資料卷
    name: my-existing-volume

資料卷標籤

volumes:
  data:
    driver: local
    labels:
      - "com.example.description=Database Volume"
      - "com.example.backup=daily"

環境變數與配置

變數替換

在 docker-compose.yml 中使用變數

services:
  web:
    image: nginx:${NGINX_VERSION:-latest}  # 預設值 latest
    ports:
      - "${WEB_PORT:-80}:80"               # 預設值 80
    environment:
      - API_URL=${API_URL}                 # 從 .env 或環境變數

.env 檔案

# .env
NGINX_VERSION=1.21
WEB_PORT=8080
API_URL=https://api.example.com

變數語法

${VARIABLE}              # 基本用法
${VARIABLE:-default}     # 如果未設定,使用 default
${VARIABLE-default}      # 如果未定義,使用 default
${VARIABLE:?error}       # 如果未設定,顯示錯誤
${VARIABLE?error}        # 如果未定義,顯示錯誤

Docker Compose 指令

1. docker-compose up - 啟動服務

# 前台啟動
docker-compose up

# 背景啟動
docker-compose up -d

# 啟動特定服務
docker-compose up web api

# 重新建構並啟動
docker-compose up --build

# 強制重新建立容器
docker-compose up --force-recreate

# 不啟動依賴的服務
docker-compose up --no-deps web

# 擴展服務實例數量
docker-compose up -d --scale web=3

2. docker-compose down - 停止並移除

# 停止並移除容器和網路
docker-compose down

# 同時移除資料卷
docker-compose down -v

# 同時移除映像
docker-compose down --rmi all

# 移除特定類型的映像
docker-compose down --rmi local  # 只移除沒有 custom tag 的映像

3. docker-compose start/stop/restart

# 啟動已存在的容器
docker-compose start

# 停止容器(不移除)
docker-compose stop

# 重啟容器
docker-compose restart

# 操作特定服務
docker-compose start web
docker-compose stop api
docker-compose restart db

4. docker-compose ps - 查看服務狀態

# 查看所有服務
docker-compose ps

# 查看特定服務
docker-compose ps web

# 顯示所有容器(包括已停止)
docker-compose ps -a

# 只顯示 ID
docker-compose ps -q

5. docker-compose logs - 查看日誌

# 查看所有服務的日誌
docker-compose logs

# 查看特定服務
docker-compose logs web

# 即時追蹤日誌
docker-compose logs -f

# 顯示最後 100 行
docker-compose logs --tail=100

# 顯示時間戳記
docker-compose logs -t

# 組合使用
docker-compose logs -f --tail=50 web api

6. docker-compose exec - 在執行中的容器執行指令

# 進入容器的 shell
docker-compose exec web bash

# 執行單一指令
docker-compose exec db psql -U postgres

# 以特定使用者執行
docker-compose exec -u root web bash

# 不分配 TTY(腳本中使用)
docker-compose exec -T web ls /app

7. docker-compose run - 執行一次性指令

# 執行指令(會建立新容器)
docker-compose run web npm test

# 不建立新的依賴容器
docker-compose run --no-deps web npm test

# 移除容器執行後
docker-compose run --rm web npm test

# 映射 port
docker-compose run -p 8080:80 web bash

# 設定環境變數
docker-compose run -e DEBUG=1 web npm start

8. docker-compose build - 建構映像

# 建構所有服務
docker-compose build

# 建構特定服務
docker-compose build web

# 不使用快取
docker-compose build --no-cache

# 並行建構
docker-compose build --parallel

# 傳遞建構參數
docker-compose build --build-arg NODE_ENV=production

9. docker-compose pull - 拉取映像

# 拉取所有映像
docker-compose pull

# 拉取特定服務
docker-compose pull web

# 安靜模式
docker-compose pull -q

10. docker-compose push - 推送映像

# 推送所有映像到倉庫
docker-compose push

# 推送特定服務
docker-compose push web

11. docker-compose config - 驗證配置

# 驗證並顯示最終配置
docker-compose config

# 只驗證,不顯示
docker-compose config -q

# 顯示服務列表
docker-compose config --services

# 顯示資料卷列表
docker-compose config --volumes

12. docker-compose top - 查看執行中的行程

# 查看所有服務的行程
docker-compose top

# 查看特定服務
docker-compose top web

13. docker-compose port - 查看 port 映射

# 查看服務的 port 映射
docker-compose port web 80
# 輸出:0.0.0.0:8080

14. docker-compose pause/unpause - 暫停/恢復

# 暫停服務
docker-compose pause

# 恢復服務
docker-compose unpause

# 操作特定服務
docker-compose pause web
docker-compose unpause web

15. 指定配置檔案

# 使用特定檔案
docker-compose -f docker-compose.prod.yml up

# 使用多個檔案(會合併)
docker-compose -f docker-compose.yml -f docker-compose.override.yml up

# 指定專案名稱
docker-compose -p myproject up

實際應用範例

範例 1:基本 Web 應用

version: '3.8'

services:
  # PostgreSQL 資料庫
  db:
    image: postgres:14
    container_name: myapp-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis 快取
  redis:
    image: redis:7-alpine
    container_name: myapp-redis
    restart: unless-stopped
    command: redis-server --requirepass redispass
    volumes:
      - redis-data:/data
    networks:
      - backend
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

  # 後端 API
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    container_name: myapp-api
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql://admin:secret@db:5432/myapp
      REDIS_URL: redis://:redispass@redis:6379
      NODE_ENV: production
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - frontend
      - backend
    volumes:
      - ./api:/app
      - /app/node_modules
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # 前端
  web:
    build:
      context: ./web
      dockerfile: Dockerfile
    container_name: myapp-web
    restart: unless-stopped
    environment:
      API_URL: http://api:3000
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - api
    networks:
      - frontend
    volumes:
      - ./web/nginx.conf:/etc/nginx/nginx.conf:ro

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  db-data:
  redis-data:

範例 2:開發環境

version: '3.8'

services:
  # 開發用資料庫
  db:
    image: postgres:14
    environment:
      POSTGRES_DB: dev_db
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev123
    ports:
      - "5432:5432"              # 開發時可直接連接
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro

  # 開發伺服器(熱重載)
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    environment:
      DATABASE_URL: postgresql://dev:dev123@db:5432/dev_db
      NODE_ENV: development
    ports:
      - "3000:3000"
      - "9229:9229"              # Node.js debugger port
    volumes:
      - ./src:/app/src           # 即時同步原始碼
      - /app/node_modules        # 不覆寫 node_modules
    command: npm run dev
    depends_on:
      - db

volumes:
  db-data:

範例 3:微服務架構

version: '3.8'

services:
  # API Gateway
  gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - frontend
      - backend
    depends_on:
      - user-service
      - order-service
      - product-service

  # 使用者服務
  user-service:
    build: ./services/user
    environment:
      DB_HOST: user-db
      REDIS_HOST: redis
    networks:
      - backend
    depends_on:
      - user-db
      - redis

  # 訂單服務
  order-service:
    build: ./services/order
    environment:
      DB_HOST: order-db
      REDIS_HOST: redis
    networks:
      - backend
    depends_on:
      - order-db
      - redis

  # 產品服務
  product-service:
    build: ./services/product
    environment:
      DB_HOST: product-db
      REDIS_HOST: redis
    networks:
      - backend
    depends_on:
      - product-db
      - redis

  # 各服務的資料庫
  user-db:
    image: postgres:14
    environment:
      POSTGRES_DB: users
    volumes:
      - user-db-data:/var/lib/postgresql/data
    networks:
      - backend

  order-db:
    image: postgres:14
    environment:
      POSTGRES_DB: orders
    volumes:
      - order-db-data:/var/lib/postgresql/data
    networks:
      - backend

  product-db:
    image: postgres:14
    environment:
      POSTGRES_DB: products
    volumes:
      - product-db-data:/var/lib/postgresql/data
    networks:
      - backend

  # 共用的 Redis
  redis:
    image: redis:7-alpine
    networks:
      - backend
    volumes:
      - redis-data:/data

networks:
  frontend:
  backend:
    internal: true

volumes:
  user-db-data:
  order-db-data:
  product-db-data:
  redis-data:

範例 4:多環境配置

docker-compose.yml(基礎配置)

version: '3.8'

services:
  web:
    build: .
    ports:
      - "80:80"
    environment:
      NODE_ENV: ${NODE_ENV:-development}

  db:
    image: postgres:14
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

docker-compose.override.yml(開發環境,自動載入)

version: '3.8'

services:
  web:
    build:
      target: development
    volumes:
      - ./src:/app/src
    command: npm run dev
    environment:
      DEBUG: "app:*"

  db:
    ports:
      - "5432:5432"

docker-compose.prod.yml(生產環境)

version: '3.8'

services:
  web:
    build:
      target: production
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  db:
    restart: always
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

使用方式

# 開發環境(自動合併 override)
docker-compose up

# 生產環境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

最佳實踐

1. 使用 .env 管理環境變數

# .env
COMPOSE_PROJECT_NAME=myapp
NODE_ENV=development
DATABASE_PASSWORD=secret123
# docker-compose.yml
services:
  db:
    environment:
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}

2. 資料持久化

推薦:使用具名資料卷

services:
  db:
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

避免:在生產環境使用綁定掛載

# 開發環境可以,生產環境不推薦
services:
  db:
    volumes:
      - ./data:/var/lib/postgresql/data

3. 網路隔離

services:
  web:
    networks:
      - frontend

  api:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend        # 只在內部網路

networks:
  frontend:
  backend:
    internal: true     # 禁止連外

4. 健康檢查

services:
  api:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    depends_on:
      api:
        condition: service_healthy

5. 限制資源

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

6. 使用 .dockerignore

# .dockerignore
node_modules
.git
.env
*.log
.DS_Store

7. 分離配置檔案

project/
├── docker-compose.yml          # 基礎配置
├── docker-compose.override.yml # 開發環境(自動載入)
├── docker-compose.prod.yml     # 生產環境
├── docker-compose.test.yml     # 測試環境
└── .env                        # 環境變數

8. 命名規範

# 使用有意義的名稱
services:
  web-frontend:      # 清楚描述服務
  api-backend:
  postgres-db:

# 使用一致的命名
networks:
  myapp-frontend
  myapp-backend

volumes:
  myapp-db-data
  myapp-uploads

疑難排解

1. 查看完整配置

docker-compose config

2. 檢查服務狀態

docker-compose ps
docker-compose logs

3. 重新建立容器

docker-compose up -d --force-recreate

4. 清理並重新啟動

docker-compose down -v
docker-compose build --no-cache
docker-compose up -d

5. 進入容器除錯

docker-compose exec web bash

總結

核心概念

  1. Services:定義容器的配置
  2. Networks:定義網路拓撲
  3. Volumes:定義資料持久化
  4. 環境變數:管理不同環境的配置

常用指令

docker-compose up -d          # 啟動
docker-compose down           # 停止並移除
docker-compose logs -f        # 查看日誌
docker-compose ps             # 查看狀態
docker-compose exec web bash # 進入容器
docker-compose build          # 建構映像

最佳實踐

  • ✅ 使用自訂網路隔離服務
  • ✅ 使用具名資料卷持久化資料
  • ✅ 使用 .env 管理環境變數
  • ✅ 配置健康檢查
  • ✅ 限制資源使用
  • ✅ 分離不同環境的配置

建立日期:2025-11-03

🔗相關文章