Featured image of post Docker Compose 完全参考:v2 配置字典与实战

Docker Compose 完全参考:v2 配置字典与实战

docker-compose / docker compose v2 完整字段解析:service / network / volume 三大顶层块、build / command / healthcheck / deploy 等 50+ 字段

Compose 是 Docker 官方推出的多容器编排工具——把一组容器 / 网络 / 卷 / 配置用一份 YAML 描述,docker compose up 一键拉起。从 v1(Python 实现)到 v2(Go 插件化,2020-08 GA)经历了一次大重构,v2 速度更快、不再是 Python 副作用、字段语义和 v1 大体兼容

这一篇把 compose 文件的所有常用字段services / networks / volumes 三大块组织成速查字典,配实战示例。

阅读对象:用 docker compose 编排多服务、想系统了解每个字段的开发者 / 运维 覆盖范围:compose v1 vs v2 差异 + service 字段字典 + networks / volumes 顶层 + 实战 YAML + compose 常用命令

一、Compose v1 vs v2:先搞清楚用哪个

维度v1v2
命令docker-compose(带横线)docker compose(空格)
实现PythonGo(Docker CLI 插件)
启动速度慢(要启 Python 解释器)快(Go 二进制)
Compose Spec1.x - 3.x3.8+ 兼容 Spec
K8s 集成实验性 kompose内置 docker compose convert
维护已停止新特性当前主推

2023 年后docker compose (v2) 是事实标准。新项目不要再用 v1

二、Compose 文件结构总览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 顶层 keys(按规范顺序)
version: "3.8"          # 文件格式版本(v2 中可选,但建议保留)
name: "my-project"      # v2.20+ 项目名(影响容器前缀)

services:               # 必填:所有服务
  web:
    image: nginx:latest
    # ... 50+ 字段

networks:               # 可选:自定义网络
  frontend:
  backend:

volumes:                # 可选:命名卷
  db-data:

configs:                # 可选:配置文件
  app-config:

secrets:                # 可选:密钥
  db-password:

Spec 是什么:Compose Spec 是 v2.0 起的"格式规范"——docker composeKomposedocker stack deploypodman compose 都按这个规范解析 YAML。比 v1 的 version: 3.x 更通用

三、service 字段字典

3.1 镜像 / 构建

字段作用版本
image指定镜像全部
build构建路径或对象全部
build.contextDockerfile 所在目录v2 起
build.dockerfileDockerfile 名(默认 Dockerfilev2 起
build.argsARG 参数v2 起
build.cache_from缓存来源镜像列表v3.2+
build.labels构建后打 labelsv3.3+
build.shm_size/dev/shm 大小v3.5+

示例:

1
2
3
4
5
6
7
8
9
services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.prod
      args:
        NODE_ENV: production
      cache_from:
        - myapp:cache

3.2 启动 / 运行时

字段作用
command覆盖默认启动命令(支持 shell 格式或 [] 格式)
entrypoint覆盖默认入口点
container_name指定容器名(docker run --name 等价)
working_dir工作目录
user容器内运行用户
tty / stdin_open是否分配 TTY / 保持 stdin
privileged特权模式
init容器内跑 init 进程(PID 1,正确转发信号)

示例:

1
2
3
4
5
6
7
8
services:
  api:
    image: myapi:latest
    command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
    user: "1000:1000"
    init: true
    tty: true
    working_dir: /app

3.3 端口 / 网络

字段作用
ports端口映射(HOST:CONTAINER
expose暴露端口(容器间可访问,不映射到宿主机)
networks加入指定网络
network_mode单一网络模式(如 host
dns / dns_search自定义 DNS
extra_hosts/etc/hosts 条目
hostname容器主机名
domainname域名
mac_addressMAC 地址

ports 短语法

1
2
3
4
5
6
7
ports:
  - "3000"                          # 容器 3000 端口,宿主机随机
  - "3000-3005"                     # 范围
  - "8000:8000"                     # 宿主机 8000:容器 8000
  - "9090-9091:8080-8081"           # 范围映射
  - "127.0.0.1:8001:8001"           # 指定宿主机 IP
  - "6060:6060/udp"                 # 指定协议

ports 长语法(v3.2+):

1
2
3
4
5
ports:
  - target: 80
    published: 8080
    protocol: tcp
    mode: host

networks 与固定 IP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
services:
  test:
    image: nginx:1.14-alpine
    networks:
      app_net:
        ipv4_address: 172.16.238.10

networks:
  app_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.16.238.0/24

3.4 存储 / 卷

字段作用
volumes挂载卷 / 目录
tmpfs挂载 tmpfs(v2+)
read_only根文件系统只读

短语法

1
2
3
4
5
6
volumes:
  - /var/lib/mysql                  # 匿名卷
  - /opt/data:/var/lib/mysql        # bind mount
  - ./cache:/tmp/cache              # 相对路径 bind
  - ~/configs:/etc/configs/:ro      # 只读
  - datavolume:/var/lib/mysql       # 引用顶层命名卷

长语法(v3.2+):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
volumes:
  - type: volume
    source: mydata
    target: /data
    volume:
      nocopy: true
  - type: bind
    source: ./static
    target: /opt/app/static
    read_only: true

3.5 环境变量 / 配置

字段作用
environment内联环境变量
env_file从文件读环境变量
secrets挂载 secret(来自顶层 secrets)
configs挂载 config(来自顶层 configs)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  app:
    environment:
      DB_HOST: db
      DB_PORT: 5432
    env_file:
      - .env
      - .env.production
    configs:
      - source: app-config
        target: /app/config.json

优先级environment > env_file > 镜像内 ENV

3.6 依赖 / 健康检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
services:
  web:
    depends_on:
      db:
        condition: service_healthy    # v2 起
      redis:
        condition: service_started    # 默认

  db:
    image: postgres:14
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

condition: service_healthy 必须配 healthcheck 才生效——v2 起推荐用这个替代 wait-for-it 脚本。

3.7 资源限制 / 重启

字段作用
restartno / always / on-failure / unless-stopped
deploy.resources.limitsCPU / 内存上限(docker stack 用)
cpus / cpusetv1 兼容字段,docker compose 仍支持
mem_limit / memswap_limitv1 兼容内存限制
ulimitsulimit 列表
pids_limitPID 上限
logging日志驱动(json-file / syslog / fluentd
shm_size/dev/shm 大小
stop_grace_period收到 SIGTERM 后等待秒数(默认 10s)
stop_signal停止信号(默认 SIGTERM)

资源限制示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
services:
  api:
    image: myapi:latest
    deploy:
      resources:
        limits:
          cpus: "0.5"      # 50% 单核
          memory: 512M
        reservations:
          cpus: "0.2"      # 预留 20%
          memory: 128M
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

Why 用 deploy.resources 而不是 mem_limit:前者是 Compose Spec 规范字段,后者是 v1 兼容字段。新项目用前者

3.8 其他

字段作用
labelsDocker 标签(LABEL 等价)
pidhost 表示共享宿主机 PID namespace
ipc共享 IPC namespace
security_optSELinux / AppArmor 选项
cap_add / cap_dropLinux capabilities
devices设备映射(docker run --device
links链接到其他容器(已废弃,用 networks)
external_links链接到 compose 外的容器
isolation隔离技术(仅 default / process / hyperv
runtime指定 runtime(runc / runsc 沙箱)
profiles启用 profile(条件启动)

profiles 示例

1
2
3
4
5
6
7
services:
  api:
    image: myapi:latest

  debug-tools:
    image: mydebug:latest
    profiles: ["debug"]
1
2
3
4
# 默认 up 不启动 debug-tools
docker compose up
# 加 profile 启动
docker compose --profile debug up

四、networks 顶层

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true    # 不通外网
  monitoring:
    driver: overlay   # 跨主机
  external_net:
    external: true    # 引用已创建的网络
    name: my-pre-existing-network

internal: true:内网隔离的 bridge——容器能互相访问,不能访问外网。数据库 / 缓存很适合。

五、volumes 顶层

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
volumes:
  db-data:
    driver: local
    driver_opts:
      type: "nfs"
      o: "addr=10.0.0.10,nolock,soft,rw"
      device: ":/path/to/dir"
  shared:
    external: true
    name: my-pre-existing-volume

六、完整实战示例

 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
version: "3.8"

services:
  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

  db:
    image: postgres:14
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    deploy:
      placement:
        constraints: [node.role == manager]

  web:
    build: ./app
    ports:
      - "8080:8080"
    networks:
      - frontend
      - backend
    depends_on:
      redis:
        condition: service_healthy
      db:
        condition: service_started
    environment:
      REDIS_HOST: redis
      DB_HOST: db
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M

networks:
  frontend:
  backend:
    internal: true

volumes:
  db-data:

关键点

  • web 同时加入 frontendbackend 网络——能访问 redis 和 db
  • dbinternal: true 的 backend 网络——不能访问外网
  • redis 多副本 + 滚动更新配置
  • web 资源限制

七、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
# 启动
docker compose up -d

# 启动指定服务
docker compose up -d web

# 不重建已停止的容器
docker compose up -d --no-recreate

# 停止 / 启动
docker compose stop
docker compose start

# 停掉 + 销毁容器
docker compose down          # 保留卷
docker compose down -v       # 同时删卷(**危险**)
docker compose down --rmi all  # 同时删镜像

# 查看状态
docker compose ps
docker compose logs -f web

# 进入容器
docker compose exec web bash

# 在 web 容器内跑一次性命令
docker compose run --rm web python manage.py migrate

八、字段优先级与兼容性

字段类型优先级
environment> env_file > 镜像 ENV
command覆盖镜像 CMD
entrypoint覆盖镜像 ENTRYPOINT
ports + expose都可以,ports 同时映射到宿主机

v1 → v2 字段迁移

v1 字段v2 推荐
mem_limitdeploy.resources.limits.memory
memswap_limitdeploy.resources.limits.memory(swap 用 flag)
cpus / cpusetdeploy.resources.limits.cpus
volume_driverdriver_opts(在 volumes 顶层)
extends已移除(用 include 或合并 YAML)

九、要点回顾

  1. Compose v2 (docker compose) 是当前主推,不要再用 v1 (docker-compose)
  2. services 是必填顶层networks / volumes / configs / secrets 可选
  3. build 支持对象语法context + dockerfile + args
  4. depends_on: condition: service_healthy 替代 wait-for-it 脚本
  5. deploy.resources.limits 才是规范字段,mem_limit 是 v1 兼容
  6. internal: true 给敏感服务(数据库)做网络隔离
  7. profiles 区分"开发 / 调试 / 生产"不同场景
  8. docker compose down -v 是核弹——会删数据卷

十、小结

Compose v2 是个"看似简单、字段多到爆炸"的工具。日常用到的不到 20 个字段

  • image / build
  • ports / networks / volumes
  • environment / env_file
  • depends_on + healthcheck
  • restart / deploy.resources.limits
  • logging

把这十几个字段摸熟,80% 的多服务编排就够用了。剩下冷门字段(cap_add / secrets / configs / pid)需要时查文档即可。

下一步:理解了 Compose,下一步是 Kubernetes——把"compose 文件"换成"YAML manifest",把 docker compose up 换成 kubectl apply,把"单机多服务"换成"集群多副本"。K8s 的 Pod 抽象比 Container 更进一步——把"应用 + 卷 + 网络"打包成不可变单元,跨节点调度。

参考资料

使用 Hugo 构建
主题 StackJimmy 设计