如何编写 Docker Compose 文件
Docker Compose 是 Docker 官方提供的工具,用于定义和运行多容器应用程序。通过一个 YAML 格式的 docker-compose.yml
文件,你可以配置服务的镜像、端口、环境变量、网络和数据卷。
1. 什么是 Docker Compose?
Docker Compose 允许你通过单一配置文件管理多容器应用程序,简化开发、测试和部署流程。它支持:
- 定义多个服务(如 Web 服务器、应用程序、数据库)。
- 配置容器间的依赖、网络和数据持久化。
- 一键启动、停止和管理所有容器。
适用场景
- 开发:快速搭建本地开发环境。
- 测试:模拟生产环境的多服务架构。
- CI/CD:自动化部署和测试。
- 生产:适合小型项目或快速原型。
2. 准备工作
确保安装:
- Docker:运行容器的核心。
- Docker Compose:通常随 Docker Desktop 安装,Linux 系统需单独安装。
验证安装:
docker --version
docker-compose --version
推荐使用代码编辑器(如 VS Code)以支持 YAML 语法高亮和验证。
3. 创建 Docker Compose 文件
3.1 文件名和格式
- 默认文件名:
docker-compose.yml
(或.yaml
)。 - 格式:YAML 语法,缩进为 2 个空格,避免 Tab。
- 验证工具:运行
docker-compose config
检查语法。
3.2 基本结构
顶级字段包括:
version
:指定 Compose 文件格式版本。services
:定义容器服务。networks
:配置服务间网络。volumes
:定义数据持久化卷。
4. 编写一个基础 Docker Compose 文件
以下是一个示例,包含 Web 服务器、应用服务和数据库,展示常见配置:
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
networks:
- app-network
depends_on:
- app
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
app:
build:
context: .
dockerfile: Dockerfile
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
- APP_ENV=production
networks:
- app-network
depends_on:
- db
restart: always
db:
image: postgres:latest
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- app-network
restart: always
volumes:
db-data:
name: db-data
networks:
app-network:
driver: bridge
5. 详细配置说明
5.1 version
- 定义 Compose 文件格式版本,如
'3.8'
。 - 版本影响支持的功能和语法:
3.x
:支持 Docker Swarm 和现代功能。- 推荐使用最新版本(截至 2025 年,
'3.8'
或更高)。
- 参考:Docker Compose 文件版本.
5.2 services
每个服务定义一个容器,常用配置包括:
5.2.1 image
- 指定预构建镜像,如
nginx:latest
(从 Docker Hub 拉取)。 - 可使用私有仓库镜像:
myregistry.com/myapp:1.0
。
5.2.2 build
- 从 Dockerfile 构建镜像:
context
:构建路径(如.
表示当前目录)。dockerfile
:指定 Dockerfile 文件名。- 示例:
build: context: ./app dockerfile: Dockerfile.prod
5.2.3 ports
- 映射主机和容器端口,格式:
"主机端口:容器端口"
。 - 示例:
"8080:80"
将主机的 8080 端口映射到容器的 80 端口。 - 支持多个端口映射:
ports: - "8080:80" - "8443:443"
5.2.4 environment
- 设置容器环境变量,支持两种格式:
- 键值对:
- KEY=VALUE
- 仅键(从
.env
文件读取):- KEY
- 键值对:
- 示例:
environment: - APP_ENV=production - DEBUG=false
5.2.5 volumes
- 挂载主机目录或命名卷:
- 主机路径:
./html:/usr/share/nginx/html:ro
(ro
表示只读)。 - 命名卷:
db-data:/var/lib/postgresql/data
。
- 主机路径:
- 命名卷在
volumes
顶级字段定义,适合持久化数据。
5.2.6 depends_on
- 指定服务启动顺序,如
web
依赖app
。 - 注意:仅控制启动顺序,不保证服务完全就绪(需配合健康检查)。
5.2.7 restart
- 定义容器重启策略:
no
:不重启(默认)。always
:始终重启。on-failure
:仅在失败时重启。unless-stopped
:除非手动停止,否则始终重启。
5.2.8 healthcheck
- 检查容器健康状态:
test
:执行的命令(如pg_isready
或curl
)。interval
:检查间隔。timeout
:超时时间。retries
:失败重试次数。
5.3 networks
网络配置决定容器间的通信方式。Docker 支持多种网络驱动程序,桥接模式(bridge
)是最常用的。
5.3.1 桥接模式(bridge
)
- 作用:在同一主机上创建隔离的网络,容器通过服务名(如
db
)相互访问。 - 特点:
- 默认网络模式,适合大多数单主机应用。
- 容器通过服务名解析 IP,无需手动配置。
- 隔离外部网络,需通过
ports
暴露到主机。
- 配置:
networks: app-network: driver: bridge
- 适用场景:Web 应用、微服务、开发测试环境。
5.3.2 其他网络模式
- host:
- 作用:容器直接使用主机的网络栈,无隔离。
- 特点:
- 性能最高,但安全性较低(无网络隔离)。
- 无法自定义
ports
,直接使用容器端口。
- 配置:
networks: default: driver: host
- 适用场景:需要高性能网络或调试网络问题。
- overlay:
- 作用:支持跨主机容器通信,专为 Docker Swarm 设计。
- 特点:
- 适合分布式集群环境。
- 需要 Swarm 模式初始化。
- 配置:
networks: swarm-network: driver: overlay
- 适用场景:生产环境中的多主机部署。
- macvlan:
- 作用:为容器分配独立 MAC 地址,像物理设备一样接入网络。
- 特点:
- 容器拥有独立 IP,适合与外部设备直接通信。
- 配置复杂,需指定子网和网关。
- 配置:
networks: macvlan-network: driver: macvlan driver_opts: parent: eth0
- 适用场景:物联网设备或需要独立 IP 的场景。
- none:
- 作用:禁用网络,容器完全隔离。
- 特点:无网络接口,仅本地通信。
- 配置:
networks: none-network: driver: none
- 适用场景:运行独立任务或安全敏感应用。
5.3.3 自定义网络
- 默认网络:不定义
networks
时,Compose 创建一个默认桥接网络。 - 自定义网络:推荐显式定义网络(如
app-network
),便于管理和隔离。 - 连接服务:
services: web: networks: - app-network
5.4 volumes
- 类型:
- 命名卷:在
volumes
定义(如db-data
),数据持久化,适合数据库。 - 绑定挂载:主机路径映射(如
./html:/usr/share/nginx/html
),适合开发时同步代码。 - 临时卷:不定义在
volumes
,容器删除后数据丢失。
- 命名卷:在
- 配置:
volumes: db-data: name: db-data
6. 高级配置
6.1 使用 .env
文件
将敏感信息放入 .env
文件:
# .env
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=mydb
在 Compose 文件中引用:
db:
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
6.2 资源限制
限制 CPU 和内存:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
6.3 健康检查
确保服务就绪:
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
6.4 扩展配置
复用配置:
# common.yml
services:
app:
environment:
- LOG_LEVEL=info
引用:
services:
app:
extends:
file: common.yml
service: app
6.5 环境特定配置
为不同环境创建文件:
docker-compose.dev.yml
:开发环境,映射本地代码。docker-compose.prod.yml
:生产环境,优化性能。
合并运行:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
7. 运行和管理 Docker Compose
7.1 常用命令
- 启动:
docker-compose up -d
(后台运行)。 - 停止并删除:
docker-compose down
(保留命名卷)。 - 查看日志:
docker-compose logs -f
(实时查看)。 - 验证配置:
docker-compose config
。 - 查看服务:
docker-compose ps
。 - 进入容器:
docker exec -it <container_name> /bin/bash
.
7.2 调试技巧
- 检查网络:
docker network ls
和docker network inspect <network_name>
。 - 端口冲突:用
docker ps
检查占用端口。 - 清理缓存:
docker-compose build --no-cache
。
8. 实际用例:WordPress 站点
搭建 WordPress 和 MySQL:
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wp_user
- WORDPRESS_DB_PASSWORD=wp_password
- WORDPRESS_DB_NAME=wordpress
networks:
- wp-network
depends_on:
- db
db:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wp_user
- MYSQL_PASSWORD=wp_password
volumes:
- wp-data:/var/lib/mysql
networks:
- wp-network
volumes:
wp-data:
networks:
wp-network:
driver: bridge
运行后,访问 http://localhost:8080
进入 WordPress 安装。
9. 最佳实践
- 版本控制:将
docker-compose.yml
纳入 Git。 - 环境隔离:使用不同 Compose 文件区分开发、测试、生产。
- 安全性:
- 使用
.env
文件存储敏感信息。 - 设置
read_only
卷或非 root 用户。
- 使用
- 网络优化:显式定义桥接网络,避免默认网络冲突。
- 文档化:为服务和配置添加注释。
10. 常见问题
- 服务无法通信?确保服务在同一网络,使用服务名(如
db
)而非localhost
。 - 端口冲突?检查主机端口占用,修改
ports
。 - 数据丢失?使用命名卷而非临时卷。
- 构建失败?检查 Dockerfile 路径,清理缓存。
11. 更多资源
- 官方文档:Docker Compose 文档