Docker Compose 配置详解
Compose 用一个 YAML 文件描述一组容器及其关系。端口决定宿主机暴露边界,卷决定容器重建后数据是否保留,网络决定服务如何互相发现。
本文按 Compose Specification 解释常用字段、短语法与长语法、多文件覆盖和生命周期命令。2026-09-11 在 Apple silicon macOS、Docker Desktop 4.86.0、Engine 29.7.2 和 Compose 5.3.1 环境实测通过完整示例的配置解析、容器启动、健康检查、HTTP 响应、绑定挂载更新和 Redis 卷持久化。本机 8080 已被占用,实测将宿主机端口改为 18080,容器端口仍为 80;正文保留更常见的 8080 并给出冲突处理方法。其他字段片段用于解释配置关系,具体项目仍应采用官方镜像、容器路径和健康检查。
Compose 文件和项目范围
推荐文件名是 compose.yaml。Compose 以项目为管理边界,默认从文件所在目录推导项目名;可以通过顶层 name、命令行 -p 或环境变量显式设置。服务、网络和命名卷的实际资源名通常带有项目前缀,因此同一配置可以在不同项目名下并存。
docker compose -p demo config
docker compose -p demo up -d现代 Compose Specification 不要求顶层 version。旧文件中的 version: "3" 可能仍可读取,但不会替代当前 Compose 实现对字段的实际支持判断。
完整配置示例
services:
web:
image: nginx:stable
ports:
- "127.0.0.1:8080:80"
volumes:
- type: bind
source: ./html
target: /usr/share/nginx/html
read_only: true
networks:
frontend:
aliases: [site]
depends_on:
cache: {condition: service_healthy}
restart: unless-stopped
cache:
image: redis:7-alpine
volumes: [redis_data:/data]
networks: [frontend]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
networks:
frontend:
driver: bridge
volumes:
redis_data:mkdir -p html
echo 'Compose works' > html/index.html
docker compose config --quiet
docker compose up -d
docker compose ps
curl -fsS http://127.0.0.1:8080顶层配置
Compose 常用顶层元素包括:
| 字段 | 作用 |
|---|---|
name | 设置 Compose 项目名 |
services | 定义需要运行的服务 |
networks | 声明服务使用的网络 |
volumes | 声明 Docker 管理的命名卷 |
configs | 向服务挂载非敏感配置 |
secrets | 向服务提供敏感文件 |
顶层 volumes 和 networks 只负责声明资源;具体服务仍需在自身的 volumes 或 networks 中引用。已有外部资源可以使用 external: true,此时 Compose 不负责创建或删除。
services:镜像、构建与启动命令
image 使用仓库、名称和标签引用镜像。build 从 Dockerfile 构建镜像;两者同时存在时,拉取和构建行为还受 pull_policy 影响。长期运行的配置应固定经过验证的标签或镜像标识。
services:
api:
build:
context: .
dockerfile: Dockerfile
image: example/api:1.0.0
command: ["./app", "serve"]command 覆盖镜像默认 CMD,entrypoint 覆盖镜像默认 ENTRYPOINT。修改前先阅读镜像文档;错误覆盖可能跳过初始化脚本。
environment、env_file 与变量插值
environment 把变量传入容器;env_file 从文件加载容器环境变量。Compose 自身还会从 Shell、.env 和命令行参数读取插值值,两者用途不同。
services:
api:
env_file:
- ./app.env
environment:
APP_MODE: production
DATABASE_PASSWORD: ${DATABASE_PASSWORD:?请在 .env 中设置}使用 ${NAME:-default} 提供默认值,使用 ${NAME:?message} 在缺少必填值时失败。docker compose config 会渲染变量并可能显示敏感值,共享输出前必须脱敏。
ports 与 expose
短语法通常写为 [HOST_IP:]HOST_PORT:CONTAINER_PORT[/PROTOCOL]:
ports:
- "127.0.0.1:8080:80"
- "127.0.0.1:8443:443"省略 HOST_IP 通常会绑定所有主机接口。反向代理后的应用宜绑定 127.0.0.1;数据库和缓存通常不发布宿主机端口。同一 Compose 网络内的服务使用服务名和容器端口通信。
expose 声明容器端口,但不会发布到宿主机。镜像的 EXPOSE 也不等同于宿主机端口映射。
volumes:命名卷与绑定挂载
命名卷由 Docker 管理,适合数据库和应用数据:
services:
db:
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:绑定挂载把宿主机路径映射到容器。相对路径按主 Compose 文件的目录解析:
services:
app:
volumes:
- ./config:/app/config:ro短语法适合简单映射;长语法可以明确 type、source、target、read_only 和绑定选项。docker compose down 默认保留命名卷,down -v 会删除项目卷。
networks:隔离与服务发现
未显式声明网络时,Compose 会创建默认网络。自定义 bridge 网络可以隔离服务并提供基于服务名和 alias 的 DNS:
services:
api:
networks: [backend]
db:
networks: [backend]
networks:
backend:
driver: bridge应用连接数据库时使用 db:5432,不要使用宿主机映射端口;容器内的 127.0.0.1 指向当前容器。固定子网仅用于确有路由要求的场景,并需避免与宿主机、VPN 和其他 Docker 网络冲突。
depends_on、healthcheck 与 restart
短格式 depends_on 只表达启动和停止顺序。需要等待依赖健康时使用长格式,并在依赖服务定义真实 healthcheck:
depends_on:
db:
condition: service_healthyhealthcheck 的命令在容器内执行,必须保证镜像包含对应工具。restart: unless-stopped 负责进程退出后的重启,不证明应用可用,也不能替代应用连接重试和外部监控。
configs 与 secrets
configs 适合非敏感配置文件,secrets 适合密码、证书或令牌文件。两者在顶层声明并由服务引用:
services:
app:
configs: [app_config]
secrets: [database_password]
configs:
app_config:
file: ./app.conf
secrets:
database_password:
file: ./secrets/database-password.txt本地 Compose 的文件型 secret 仍依赖宿主机文件权限。不要把 secret 源文件提交到公开仓库。
profiles 与可选服务
profiles 让调试或管理服务只在指定场景启动:
services:
toolbox:
image: alpine:3.21
command: ["sleep", "infinity"]
profiles: [debug]默认执行 docker compose up -d 不会启动 toolbox;使用 docker compose --profile debug up -d 才会启用。
多文件合并与复用
基础配置和生产覆盖可以分开保存:
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -d后一个文件会按 Compose 合并规则覆盖或追加字段,路径解析和序列合并并不都等同于简单文本覆盖。发布前必须检查最终 config 输出。x- 扩展字段和 YAML anchors 可以减少重复,但过度复用会降低可读性。
日志与资源设置
日志轮转可以限制本地日志增长:
logging:
driver: json-file
options: {max-size: "10m", max-file: "3"}资源限制的可用字段取决于 Compose 实现和运行模式。不要默认认为 Swarm 的 deploy.resources 在所有单机 Compose 环境中具有完全相同的行为。
生产环境安全加固
限制发布端口,保护 .env 和 Docker socket,配置日志轮转,并在执行删除卷前先备份。
生命周期与更新
docker compose pull
docker compose up -d
docker compose logs --tail=100 web
docker compose restart web
docker compose stop
docker compose down升级前先备份卷和数据库,运行 docker compose config --quiet,保留旧镜像和配置。数据库迁移可能不可逆,回滚应恢复升级前备份。危险操作: docker compose down -v 和全局 prune 命令可能删除数据,执行前先备份并确认范围。
验证配置与运行结果
docker compose ps
docker compose logs --tail=100 web
docker inspect "$(docker compose ps -q cache)" --format '{{json .State.Health}}'
curl -fsS http://127.0.0.1:8080修改 html/index.html 后无需重建容器;再次请求页面应立即看到新内容,证明绑定挂载有效。
只运行 docker compose config --quiet 属于静态校验;只有启动容器并检查状态、日志、应用响应和数据持久化后,才能声称完成运行验证。
常见问题
服务无法连接缓存
确认服务加入同一网络,并使用 cache:6379;执行 docker network inspect 检查成员。
端口冲突
ss -ltnp | grep ':8080 ' || true更换宿主机端口,容器端口保持 80。
网络地址池耗尽
检查 docker network ls、docker network inspect bridge 和 ip route,确认 VPN 与 Docker 子网不重叠。
配置完成后
将 Compose 文件纳入版本控制,将 .env 交给密钥管理,为卷和数据库设置异机备份,并在升级前完成恢复演练。
总结
Compose 把服务、构建、命令、变量、端口、卷、网络、依赖和健康检查集中到一个可审阅文件。先用 docker compose config 查看最终模型,再执行启动和分层验收,可以在修改生效前发现大部分配置错误。