Docker Compose 文件参考
Docker Compose 文件(docker-compose.yml)是定义多容器应用的核心配置文件。本文将详细介绍 Compose 文件的完整语法和配置选项。
目录
文件格式
1.1 版本说明
yaml
# Compose 文件版本
version: '3.8' # 推荐版本
# 版本演进:
# - 1.x: 旧版格式
# - 2.x: 支持网络、卷
# - 3.x: 支持 Swarm 部署1.2 文件结构
yaml
version: '3.8'
services:
# 服务定义
networks:
# 网络定义
volumes:
# 卷定义
configs:
# 配置定义
secrets:
# 密钥定义1.3 多文件配置
yaml
# docker-compose.yml (基础配置)
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
# docker-compose.override.yml (自动加载,开发环境)
version: '3.8'
services:
web:
volumes:
- ./html:/usr/share/nginx/html
# docker-compose.prod.yml (生产环境)
version: '3.8'
services:
web:
deploy:
replicas: 3服务配置
2.1 基本服务配置
yaml
services:
web:
# 镜像或构建
image: nginx:alpine
# 或
build:
context: ./web
dockerfile: Dockerfile.prod
# 容器名称
container_name: my-web
# 主机名
hostname: web
# 域名
domainname: example.com
# 用户名/UID
user: "1000:1000"
# 工作目录
working_dir: /app
# 入口点
entrypoint: ["/app/entrypoint.sh"]
# 命令
command: ["nginx", "-g", "daemon off;"]
# 环境变量
environment:
- NODE_ENV=production
- DEBUG=1
# 环境变量文件
env_file:
- .env
- .env.local2.2 端口映射
yaml
services:
web:
# 短语法
ports:
- "3000" # 只暴露容器端口(随机主机端口)
- "8080:80" # 主机:容器
- "127.0.0.1:8080:80" # 绑定地址
- "127.0.0.1:8080-8090:80-90" # 范围
- "8080:80/udp" # 指定协议
# 长语法(推荐)
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
- target: 443
published: 8443
protocol: tcp
mode: host2.3 卷挂载
yaml
services:
web:
# 短语法
volumes:
- /var/lib/mysql # 命名卷
- /opt/data:/var/lib/mysql # 绑定挂载
- ./cache:/tmp/cache:ro # 只读
- data-volume:/var/lib/mysql # 使用命名卷
# 长语法(推荐)
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./config
target: /config
read_only: true
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
mode: 17702.4 网络配置
yaml
services:
web:
# 连接网络
networks:
- frontend
- backend
# 网络别名
networks:
frontend:
aliases:
- web-alias
backend:
aliases:
- api-server
# 静态 IP
networks:
frontend:
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10
# DNS 配置
dns:
- 8.8.8.8
- 8.8.4.4
dns_search:
- example.com
dns_opt:
- ndots:2
# 额外主机
extra_hosts:
- "database:192.168.1.100"
- "cache:192.168.1.101"
# 主机网络模式
network_mode: host
# 或
network_mode: "service:service_name"
# 或
network_mode: "container:container_name"2.5 依赖关系
yaml
services:
web:
# 简单依赖(只控制启动顺序)
depends_on:
- db
- redis
# 带条件的依赖(Compose v3+)
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
# 链接(已弃用,使用网络代替)
links:
- "db:database"
- "redis"2.6 健康检查
yaml
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
disable: false
# 或使用命令字符串
healthcheck:
test: "curl -f http://localhost:8080/health || exit 1"
interval: 30s
timeout: 10s
retries: 32.7 资源限制
yaml
services:
web:
# 部署配置(Swarm 模式)
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
pids: 100
reservations:
cpus: '0.25'
memory: 256M
# 重启策略
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
# 更新配置
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
# 回滚配置
rollback_config:
parallelism: 1
delay: 10s
failure_action: pause
# 副本数
replicas: 3
# 放置约束
placement:
constraints:
- node.role == worker
- node.labels.zone == public
preferences:
- spread: node.labels.rack
# 模式
mode: replicated # 或 global
# 非 Swarm 模式的资源限制
mem_limit: 512m
memswap_limit: 1g
mem_reservation: 256m
cpus: '0.5'
cpu_shares: 512
cpu_quota: 50000
cpu_period: 100000
cpuset: '0,1'2.8 日志配置
yaml
services:
web:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "production_status"
env: "OS_VERSION"
# 或使用其他驱动
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"
# 禁用日志
logging:
driver: none2.9 安全配置
yaml
services:
web:
# 只读根文件系统
read_only: true
# 用户
user: "1000:1000"
# 组
group_add:
- mail
# 安全选项
security_opt:
- no-new-privileges:true
- seccomp:unconfined
- apparmor:docker-default
# 能力
cap_add:
- NET_ADMIN
cap_drop:
- ALL
# 特权模式
privileged: false
# 设备
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
# 系统控制
sysctls:
- net.core.somaxconn=1024
- net.ipv4.ip_forward=1
# ulimit
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 400002.10 构建配置
yaml
services:
web:
build:
# 构建上下文
context: ./web
# Dockerfile 路径
dockerfile: Dockerfile.prod
# 构建参数
args:
- NODE_ENV=production
- VERSION=1.0.0
# 缓存源
cache_from:
- myapp/web:latest
- myapp/web:cache
# 标签
labels:
- "com.example.description=Web application"
- "com.example.department=IT"
# 目标(多阶段构建)
target: production
# 网络
network: host
# 秘密
secrets:
- npmrc
# SSH
ssh:
- default
# 额外主机
extra_hosts:
- "npm.registry:192.168.1.100"
# 隔离
isolation: default2.11 其他配置
yaml
services:
web:
# 暴露端口(不发布到主机)
expose:
- "3000"
- "8080"
# 外部连接
external_links:
- redis_1
- project_db_1:mysql
# PID 模式
pid: host
# IPC 模式
ipc: host
# 或
ipc: "service:service_name"
# 或
ipc: "shareable"
# cgroup 模式
cgroup: host
# 初始化进程
init: true
# 标准输入
stdin_open: true
# 伪终端
tty: true
# 环境
environment:
- TERM=xterm-256color
# 停止信号
stop_signal: SIGTERM
# 停止超时
stop_grace_period: 30s
# 重启
restart: unless-stopped
# always, on-failure, unless-stopped, no
# 标签
labels:
- "com.example.service=web"
- "com.example.environment=production"
# 设备 cgroup 规则
device_cgroup_rules:
- "c 1:3 mr"
- "a 7:* rmw"网络配置
3.1 网络定义
yaml
networks:
# 基本网络
frontend:
driver: bridge
# 高级配置
backend:
driver: bridge
driver_opts:
com.docker.network.bridge.name: backend-bridge
com.docker.network.bridge.enable_icc: "true"
com.docker.network.bridge.enable_ip_masquerade: "true"
ipam:
driver: default
config:
- subnet: 172.28.0.0/16
ip_range: 172.28.5.0/24
gateway: 172.28.5.254
aux_addresses:
host1: 172.28.1.5
host2: 172.28.1.6
options:
foo: bar
internal: true
attachable: true
labels:
- "com.example.description=Backend network"
# 外部网络
existing-network:
external: true
name: my-pre-existing-network
# Overlay 网络(Swarm)
overlay-network:
driver: overlay
attachable: true
driver_opts:
encrypted: "true"卷配置
4.1 卷定义
yaml
volumes:
# 基本卷
db-data:
driver: local
# 高级配置
app-data:
driver: local
driver_opts:
type: nfs
o: addr=192.168.1.100,rw
device: ":/path/to/dir"
labels:
- "com.example.description=Application data"
# 外部卷
existing-volume:
external: true
name: my-pre-existing-volume
# 命名卷
named-volume:
driver: local
driver_opts:
size: 10GiB配置和密钥
5.1 配置(Configs)
yaml
configs:
# 文件配置
nginx-config:
file: ./nginx.conf
labels:
- "com.example.description=Nginx configuration"
# 外部配置
external-config:
external: true
name: my-pre-existing-config
# 环境变量配置
env-config:
environment: CONFIG_DATA
labels:
- "com.example.description=Environment config"
services:
web:
image: nginx:alpine
configs:
- source: nginx-config
target: /etc/nginx/nginx.conf
uid: '0'
gid: '0'
mode: 04405.2 密钥(Secrets)
yaml
secrets:
# 文件密钥
db-password:
file: ./secrets/db-password.txt
labels:
- "com.example.description=Database password"
# 外部密钥
external-secret:
external: true
name: my-pre-existing-secret
# 环境变量密钥
env-secret:
environment: SECRET_DATA
services:
db:
image: postgres:15-alpine
secrets:
- source: db-password
target: /run/secrets/db-password
uid: '0'
gid: '0'
mode: 0400
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db-password扩展字段
6.1 扩展字段(x-)
yaml
# 定义可复用的扩展字段
x-common-variables: &common-variables
TZ: Asia/Shanghai
LANG: en_US.UTF-8
x-common-deploy: &common-deploy
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
services:
web:
image: nginx:alpine
environment:
<<: *common-variables
NGINX_HOST: localhost
deploy:
<<: *common-deploy
replicas: 3
api:
image: myapi:latest
environment:
<<: *common-variables
API_PORT: 8080
deploy:
<<: *common-deploy
replicas: 26.2 环境变量插值
yaml
version: '3.8'
services:
web:
image: "${WEB_IMAGE:-nginx:alpine}"
ports:
- "${WEB_PORT:-80}:80"
environment:
- NODE_ENV=${NODE_ENV:-production}
- DEBUG=${DEBUG:-false}
deploy:
replicas: ${REPLICAS:-1}
# 必需变量
environment:
- DATABASE_URL=${DATABASE_URL:?DATABASE_URL is required}6.3 条件配置
yaml
services:
web:
image: nginx:alpine
ports:
- "80:80"
${PRODUCTION:+deploy:}
${PRODUCTION:+replicas: 3}
${PRODUCTION:+restart_policy:}
${PRODUCTION:+condition: any}完整示例
yaml
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: nginx-proxy
hostname: nginx
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
volumes:
- type: bind
source: ./nginx/nginx.conf
target: /etc/nginx/nginx.conf
read_only: true
- type: bind
source: ./nginx/ssl
target: /etc/nginx/ssl
read_only: true
- type: volume
source: nginx-cache
target: /var/cache/nginx
networks:
- frontend
depends_on:
- web
- api
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
logging:
driver: json-file
options:
max-size: 10m
max-file: 3
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.rule=Host(`example.com`)"
web:
build:
context: ./web
dockerfile: Dockerfile
args:
- NODE_ENV=production
target: production
image: myapp/web:${VERSION:-latest}
environment:
- NODE_ENV=production
- API_URL=http://api:8080
- REDIS_URL=redis://redis:6379
volumes:
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
networks:
- frontend
- backend
depends_on:
api:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
restart_policy:
condition: any
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- node.role == worker
preferences:
- spread: node.labels.zone
api:
build:
context: ./api
dockerfile: Dockerfile
image: myapp/api:${VERSION:-latest}
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=app
- DB_USER=api
- REDIS_HOST=redis
- REDIS_PORT=6379
secrets:
- source: db-password
target: /run/secrets/db-password
mode: 0400
networks:
- backend
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
replicas: 2
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: api
POSTGRES_DB: app
POSTGRES_INITDB_ARGS: --encoding=UTF-8
PGDATA: /var/lib/postgresql/data/pgdata
secrets:
- source: db-password
target: /run/secrets/db-password
mode: 0400
volumes:
- type: volume
source: db-data
target: /var/lib/postgresql/data
- type: bind
source: ./db/init
target: /docker-entrypoint-initdb.d
read_only: true
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U api -d app"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
deploy:
placement:
constraints:
- node.role == manager
resources:
limits:
memory: 1G
reservations:
memory: 512M
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- type: volume
source: redis-data
target: /data
networks:
- backend
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 128M
networks:
frontend:
driver: bridge
driver_opts:
com.docker.network.bridge.name: frontend
labels:
- "com.example.description=Frontend network"
backend:
driver: bridge
internal: true
driver_opts:
com.docker.network.bridge.name: backend
com.docker.network.bridge.enable_icc: "true"
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
labels:
- "com.example.description=Backend network"
volumes:
db-data:
driver: local
driver_opts:
type: none
o: bind
device: /data/db
labels:
- "com.example.description=Database data"
redis-data:
driver: local
nginx-cache:
driver: local
secrets:
db-password:
file: ./secrets/db-password.txt
labels:
- "com.example.description=Database password"