第3章 编写第一个 docker-compose.yml:服务定义、镜像选择、端口映射、卷挂载、环境变量
3.1 原理概述
docker-compose.yml 是 Docker Compose 的核心配置文件,它以 YAML 格式声明一组多容器应用的服务定义、网络、卷以及运行时参数。每条 service 本质是对 docker run 命令的抽象,通过声明式语法实现可重复、可版本管理的环境装配。
本章聚焦四个必配要素:
- 服务定义(
services:)—— 容器编排的最小单元 - 镜像选择(
image:)—— 决定运行时依赖 - 端口映射(
ports:)—— 对外暴露服务入口 - 卷挂载(
volumes:)—— 数据持久化与热更新 - 环境变量(
environment:)—— 注入配置参数
学习目标:手写一份能启动 Nginx + Redis 测试环境的 Compose 文件,并验证端口、日志与数据目录的挂载效果。
3.2 实现流程
- 在项目根目录创建
docker-compose.yml - 定义服务名称(如
web、cache) - 选择官方镜像并指定版本标签
- 配置端口映射:宿主机端口:容器端口
- 配置卷挂载:宿主机路径:容器路径
- 添加环境变量键值对
- 执行
docker compose up -d启动验证
3.3 核心配置详解
3.3.1 服务定义与镜像选择
每个服务以顶层 key 声明,image 字段指定可用的镜像仓库与标签。
services:
web:
image: nginx:1.25-alpine
cache:
image: redis:7.2-alpine
| 策略 | 示例 | 适用场景 |
|---|---|---|
| 指定小版本 | nginx:1.25.3 |
生产环境固定版本 |
| 使用滚动标签 | nginx:latest |
本地快速试验 |
| Alpine 精简版 | redis:7-alpine |
节省镜像体积 & CI 环境 |
| 自定义构建镜像 | build: ./app |
需要定制 Dockerfile |
3.3.2 端口映射
格式:宿主机IP:宿主机端口:容器端口(IP 可省略)。
services:
web:
image: nginx:1.25-alpine
ports:
- "8080:80" # 宿主机所有IP的8080→容器80
- "127.0.0.1:8081:80" # 仅绑定本地回环
常见错误:若同时启动多个服务映射相同宿主机端口,Compose 会报
port is already allocated。请确保端口唯一。
3.3.3 卷挂载
支持命名卷(由 Compose 管理)与绑定挂载(直接映射宿主机路径)。
services:
web:
image: nginx:1.25-alpine
volumes:
- ./html:/usr/share/nginx/html # 绑定挂载,用于静态文件热更
cache:
image: redis:7.2-alpine
volumes:
- redis-data:/data # 命名卷,持久化数据
volumes:
redis-data: # 顶层声明命名卷
3.3.4 环境变量
使用 environment 或 env_file 注入配置。
services:
cache:
image: redis:7.2-alpine
environment:
- REDIS_PASSWORD=mysecret
- REDIS_MAXMEMORY=256mb
3.4 完整示例:Nginx + Redis 测试环境
将以上要素整合为一份可运行的 Compose 文件:
version: "3.9"
services:
web:
image: nginx:1.25-alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
cache:
image: redis:7.2-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
environment:
- REDIS_PASSWORD=devpass
volumes:
redis-data:
3.5 调试与验证
启动服务后,使用以下命令验证配置是否生效:
# 启动所有服务(后台)
docker compose up -d
# 查看服务状态
docker compose ps
# 查看运行日志(实时追踪 web 服务)
docker compose logs -f web
# 验证端口映射(从宿主机访问)
curl -I http://localhost:8080
# 检查卷挂载是否写入
echo "Hello from bind mount" | tee ./html/index.html
curl http://localhost:8080/index.html
3.6 常见错误与稳定性建议
| 错误场景 | 典型提示 | 解决方案 |
|---|---|---|
| 端口被占用 | port is already allocated |
检查 netstat -tulpn,更换宿主机端口 |
| 镜像拉取失败 | manifest for ... not found |
确认镜像标签存在;使用 docker pull 测试 |
| 卷挂载权限拒绝 | Permission denied |
宿主机目录加 chmod 755 或使用 :Z SELinux 标签 |
| 环境变量未生效 | 容器内 printenv 无变量 |
检查缩进;使用 env_file 代替内联 |
性能与稳定性优化:
- 避免使用
- 绑定挂载适合开发,生产环境优先使用命名卷;
- 敏感变量(密码、)不要直接写在 YAML 中,使用
- 避免使用
latest 标签在反复环境下引入不可控更新;- 绑定挂载适合开发,生产环境优先使用命名卷;
- 敏感变量(密码、)不要直接写在 YAML 中,使用
.env 文件或 Docker Secrets。
3.7 本章小结
通过手写第一份 docker-compose.yml,你已经掌握了声明式服务编排的四个核心要素:镜像选择、端口映射、卷挂载、环境变量。配合调试命令 docker compose up -d、logs、ps,可以快速验证配置正确性。接下来的章节将在此基础上添加网络、依赖控制与多环境部署。