15.8.2 docker-compose.yml结构与语法规范
本节围绕 docker-compose.yml 的结构与语法规范展开,目标是编写可读、可维护、可扩展的多容器编排文件。根级通常包含 services、networks、volumes、configs、secrets(version 可省略)。建议统一 2 空格缩进、服务命名清晰、显式声明网络与卷、配置与数据分离、最小端口暴露。
原理草图(Compose 解析与运行关系):
核心结构与语法示例(可直接执行):
# 文件: /opt/app/docker-compose.yml
services:
web:
image: nginx:1.25.4
container_name: app_web
ports:
- "8080:80" # 宿主端口:容器端口
environment:
- TZ=Asia/Shanghai
volumes:
- ./nginx/html:/usr/share/nginx/html:ro
networks:
- app_net
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost/ || exit 1"]
interval: 10s
timeout: 3s
retries: 3
db:
image: mysql:8.0.36
container_name: app_db
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: app
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
networks:
- app_net
restart: unless-stopped
networks:
app_net:
driver: bridge
volumes:
db_data:
配套变量文件(避免明文写入敏感信息):
# 文件: /opt/app/.env
MYSQL_ROOT_PASSWORD=StrongPassw0rd!
关键字段说明与常见写法:
- image:指定镜像;build:指定构建上下文。二选一或组合使用(构建并打 tag)。
- ports:对外映射端口,格式 "宿主:容器";expose:仅服务内部可见。
- volumes:命名卷或绑定挂载,建议明确读写权限 :ro/:rw。
- depends_on:仅控制启动顺序,不保证服务可用,应配合 healthcheck 与应用重试。
- networks:显式指定网络,避免默认网络名随 project 变化导致冲突。
- environment / env_file:环境变量推荐写在 .env;敏感信息优先 secrets(生产)。
验证与运行(含命令解释):
# 1) 进入目录
cd /opt/app
# 2) 校验语法并查看最终渲染(含变量替换)
docker compose config
# 预期: 输出完整的合并配置,确认端口/环境变量/卷是否正确
# 3) 启动
docker compose up -d
# 预期: 创建网络/卷并启动 web、db
# 4) 查看状态
docker compose ps
# 预期: web、db 状态为 "running"
# 5) 查看日志
docker compose logs -f web
配置复用(YAML 锚点)示例(减少重复):
# 文件: /opt/app/docker-compose.yml
x-common: &common
restart: unless-stopped
networks:
- app_net
services:
web:
<<: *common
image: nginx:1.25.4
ports: ["8080:80"]
api:
<<: *common
image: alpine:3.19
command: ["sh", "-c", "echo ok && sleep 3600"]
networks:
app_net:
安装与环境准备(Compose v2):
# 查看 Docker 与 Compose 版本
docker version
docker compose version
# 若 compose 命令不可用,确认 Docker 版本 >= 20.10
# RHEL/CentOS: 通过官方仓库安装 Docker 后自带 compose 插件
常见排错与修复:
1) 端口冲突
# 报错: bind: address already in use
ss -lntp | grep 8080
# 处理: 修改 ports 映射或停止占用进程
2) 变量未加载导致空值
# 排查 .env 是否在 compose 文件同目录
ls -la /opt/app/.env
docker compose config | grep MYSQL_ROOT_PASSWORD
# 处理: 补充 .env 或改用 env_file
3) 依赖服务未就绪
# 表现: web 启动但连接 db 失败
docker compose logs web
# 处理: 为 db 添加 healthcheck;应用侧增加重试
练习:
1) 将 web 服务端口从 8080 改为 8088,并验证 curl http://127.0.0.1:8088 返回 nginx 欢迎页。
2) 增加一个 redis 服务,使用命名卷持久化 /data,并在 web 中设置环境变量 REDIS_HOST=redis。
3) 使用 docker compose config 输出渲染结果,确认变量替换与卷/网络名是否符合预期。