Docker Compose 編寫指南

Docker Compose 編寫指南

什麼是 Docker Compose?

Docker Compose 是一個用於定義和管理多容器 Docker 應用程式的工具。透過 YAML 檔案來配置應用程式的服務、網路和資料卷,讓您可以用單一命令來建立和啟動所有相關的服務。

Docker Compose 的優勢

  • 簡化多容器管理:用一個檔案定義整個應用程式架構
  • 環境一致性:確保開發、測試、生產環境的一致性
  • 快速部署:一鍵啟動整個應用程式堆疊
  • 服務編排:輕鬆管理服務間的依賴關係
  • 可重現性:版本控制友好,便於團隊協作

使用場景

  • 微服務架構:管理多個相互依賴的服務
  • 開發環境:快速搭建完整的開發環境
  • 測試環境:創建隔離的測試環境
  • CI/CD 流程:自動化部署和測試

基本概念

核心組件

  • Services(服務):定義容器的配置,包括映像檔、端口、環境變數等
  • Networks(網路):管理容器間的網路通訊
  • Volumes(資料卷):處理資料持久化和共享

檔案結構

1
2
3
4
5
6
7
8
version: '3.8'      # Compose 檔案版本
services: # 服務定義
service1:
# 服務配置
networks: # 網路定義(可選)
# 網路配置
volumes: # 資料卷定義(可選)
# 資料卷配置

完整範例:Spring Boot 應用程式

以下是一個 Spring Boot 應用程式的 Docker Compose 配置範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
version: '3.8'

services:
dockertest:
build:
context: .
dockerfile: Dockerfile
args:
MAVEN_PROFILE: dev
SPRING_PROFILE: dev
image: dockertest:latest
container_name: dockertest-dev
ports:
- "80:8080"
environment:
- SPRING_PROFILES_ACTIVE=dev
- JAVA_OPTS=-Xmx512m -Xms256m -Dspring.profiles.active=dev
volumes:
# 使用 named volume 避免權限問題
- dev-logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
restart: unless-stopped
networks:
- app-network

networks:
app-network:
driver: bridge

# Named volume for development logs
volumes:
dev-logs:
driver: local

配置詳解

1. 版本聲明

1
version: '3.8'
  • 目的:指定 Docker Compose 檔案格式版本
  • 建議:使用 3.8 或更新版本以支援最新功能

2. 服務構建配置

1
2
3
4
5
6
build:
context: .
dockerfile: Dockerfile
args:
MAVEN_PROFILE: dev
SPRING_PROFILE: dev
  • context:建構上下文路徑
  • dockerfile:指定 Dockerfile 檔案
  • args:傳遞建構參數

3. 端口映射

1
2
ports:
- "80:8080"
  • 格式"主機端口:容器端口"
  • 用途:讓外部可以存取容器內的服務

4. 環境變數

1
2
3
environment:
- SPRING_PROFILES_ACTIVE=dev
- JAVA_OPTS=-Xmx512m -Xms256m
  • 格式一:列表格式 - KEY=VALUE
  • 格式二:字典格式 KEY: VALUE

5. 資料卷掛載

1
2
3
4
volumes:
- dev-logs:/app/logs # Named volume
- ./config:/app/config:ro # Bind mount (唯讀)
- /var/run/docker.sock:/var/run/docker.sock # Socket 掛載

6. 健康檢查

1
2
3
4
5
6
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

7. 重啟策略

1
restart: unless-stopped
  • no:不自動重啟(預設)
  • always:總是重啟
  • on-failure:失敗時重啟
  • unless-stopped:除非手動停止,否則總是重啟

8. 網路配置

1
2
networks:
- app-network
  • 功能:將服務加入指定網路
  • 用途:實現服務間的網路隔離和通訊管理

常用配置選項

服務配置

選項 功能 範例
image 指定映像檔 image: nginx:latest
build 建構配置 build: .
ports 端口映射 ports: ["80:8080"]
environment 環境變數 environment: NODE_ENV=production
volumes 資料卷掛載 volumes: ["./data:/app/data"]
networks 網路配置 networks: ["app-net"]
depends_on 服務依賴 depends_on: ["db"]
restart 重啟策略 restart: always
command 覆寫命令 command: nginx -g 'daemon off;'
entrypoint 覆寫入口點 entrypoint: /app/start.sh

網路類型

1
2
3
4
5
6
7
8
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 內部網路,無法存取外部
overlay-net:
driver: overlay # 用於 Swarm 模式

資料卷類型

1
2
3
4
5
6
7
8
9
10
11
12
volumes:
# Named volume
mysql-data:
driver: local

# NFS volume
nfs-data:
driver: local
driver_opts:
type: nfs
o: addr=192.168.1.100,rw
device: ":/path/to/dir"

常用命令

基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 啟動服務(背景執行)
docker-compose up -d

# 查看服務狀態
docker-compose ps

# 查看服務日誌
docker-compose logs

# 查看特定服務日誌
docker-compose logs dockertest

# 停止服務
docker-compose stop

# 停止並刪除容器
docker-compose down

# 停止並刪除容器、網路、資料卷
docker-compose down -v

建構和更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 建構映像檔
docker-compose build

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

# 強制重新建構
docker-compose build --no-cache

# 拉取最新映像檔
docker-compose pull

# 重啟服務
docker-compose restart dockertest

擴展和管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 擴展服務實例
docker-compose up -d --scale web=3

# 執行一次性命令
docker-compose exec dockertest bash

# 在新容器中執行命令
docker-compose run dockertest python manage.py migrate

# 查看配置
docker-compose config

# 驗證配置檔案
docker-compose config --quiet

環境管理

多環境配置

基礎配置:docker-compose.yml

1
2
3
4
5
6
version: '3.8'
services:
app:
build: .
environment:
- NODE_ENV=${NODE_ENV:-development}

開發環境:docker-compose.override.yml

1
2
3
4
5
6
7
8
9
version: '3.8'
services:
app:
volumes:
- .:/app
ports:
- "3000:3000"
environment:
- DEBUG=true

生產環境:docker-compose.prod.yml

1
2
3
4
5
6
version: '3.8'
services:
app:
restart: always
environment:
- NODE_ENV=production

使用特定配置檔案

1
2
3
4
5
6
7
8
9
10
11
# 使用生產環境配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# 使用開發環境配置(啟動服務)
docker compose -f docker-compose.dev.yml up -d

# 使用開發環境配置(停止並清理)
docker compose -f docker-compose.dev.yml down -v

# 使用環境變數檔案
docker-compose --env-file .env.prod up -d

命令說明:

  • -f:指定使用的 Docker Compose 檔案
  • up -d:背景啟動服務
  • down -v:停止服務並刪除相關的資料卷
  • 可以同時指定多個配置檔案,後面的會覆蓋前面的設定

環境變數檔案 (.env)

1
2
3
4
# .env
COMPOSE_PROJECT_NAME=myapp
POSTGRES_PASSWORD=secretpassword
APP_VERSION=1.0.0

最佳實踐

1. 檔案組織

1
2
3
4
5
6
7
8
9
10
project/
├── docker-compose.yml # 基礎配置
├── docker-compose.override.yml # 開發環境覆蓋
├── docker-compose.prod.yml # 生產環境配置
├── docker-compose.test.yml # 測試環境配置
├── .env # 環境變數
├── .env.example # 環境變數範例
└── dockerfiles/ # 自定義 Dockerfile
├── app.Dockerfile
└── nginx.Dockerfile

2. 安全性考量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用非 root 使用者
services:
app:
user: "1001:1001"

# 限制容器權限
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE

# 使用 secrets 管理敏感資料
secrets:
db_password:
file: ./secrets/db_password.txt

services:
app:
secrets:
- db_password

3. 資源限制

1
2
3
4
5
6
7
8
9
10
services:
app:
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'

4. 健康檢查

1
2
3
4
5
6
7
8
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s

故障排除

常見問題

Q1: 服務無法啟動?

1
2
3
4
5
6
7
8
# 檢查配置語法
docker-compose config

# 查看詳細錯誤信息
docker-compose up --no-deps service-name

# 檢查服務日誌
docker-compose logs service-name

Q2: 端口衝突?

1
2
3
4
5
6
# 查看端口使用情況
netstat -tulpn | grep :8080

# 修改端口映射
ports:
- "8081:8080" # 改用其他主機端口

Q3: 資料遺失?

1
2
3
4
5
6
7
8
9
# 使用 named volumes 確保資料持久化
volumes:
postgres-data:
driver: local

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

除錯技巧

1
2
3
4
5
6
7
8
9
10
11
# 進入容器進行除錯
docker-compose exec service-name bash

# 查看容器內程序
docker-compose exec service-name ps aux

# 檢查網路連接
docker-compose exec service-name ping other-service

# 查看環境變數
docker-compose exec service-name env

進階配置

日誌管理

1
2
3
4
5
6
7
8
9
10
11
12
version: '3.8'

services:
dockertest:
build: .
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
- ./logs:/app/logs

資源限制

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3.8'

services:
dockertest:
build: .
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'

提示
建議在開發環境使用 docker-compose.override.yml 來覆蓋生產環境配置

重要提示
在生產環境中,請務必設定適當的資源限制、健康檢查和重啟策略

安全提醒
避免在 Docker Compose 檔案中硬編碼敏感資料,使用環境變數或 Docker Secrets

📺 實戰教學影片:編寫docker-compose快速部屬環境