Docker Compose 多容器编排:从入门到实战
一、什么是 Docker Compose?
1.1 定义
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件配置应用的服务、网络和卷,然后使用一个命令就可以创建和启动所有服务。
1.2 为什么需要 Compose?
没有 Compose 时,启动一个 Web 应用需要:
bash
docker network create myapp
docker volume create db-data
docker run -d --network myapp --name db -v db-data:/var/lib/mysql mysql:8.0
docker run -d --network myapp --name redis redis:alpine
docker run -d --network myapp -p 8080:8080 --depends-on db,redis myapp:latest
使用 Compose 后,一个文件搞定:
yaml
services:
db:
image: mysql:8.0
volumes:
- db-data:/var/lib/mysql
networks:
- myapp
redis:
image: redis:alpine
networks:
- myapp
app:
build: .
ports:
- "8080:8080"
depends_on:
- db
- redis
networks:
- myapp
volumes:
db-data:
networks:
myapp:
1.3 核心概念
- Service:一个服务对应一个容器
- Project:一组关联的服务,由一个 compose 文件定义
- Compose File:YAML 格式,定义服务、网络、卷等配置
二、安装与基础
2.1 安装
Docker Compose 已集成到 Docker 中(Docker Compose V2)。安装 Docker 时自动包含。
bash
# 验证安装
docker compose version
# 输出: Docker Compose version v2.x.x
# 旧版本(独立安装)
docker-compose version
2.2 基本使用流程
bash
# 1. 编写 docker-compose.yml
# 2. 启动所有服务
docker compose up
# 后台运行
docker compose up -d
# 3. 查看服务状态
docker compose ps
# 4. 查看日志
docker compose logs
docker compose logs -f # 实时跟踪
# 5. 停止并删除所有服务
docker compose down
# 6. 停止服务(不删除)
docker compose stop
# 7. 重启服务
docker compose restart
三、docker-compose.yml 详解
3.1 基本结构
yaml
services: # 定义服务
service-name:
image: ...
build: ...
ports: ...
...
volumes: # 定义数据卷
volume-name:
networks: # 定义网络
network-name:
configs: # 定义配置
secrets: # 定义密钥
3.2 服务配置项
镜像与构建
yaml
services:
web:
# 方式一:使用现有镜像
image: nginx:latest
# 方式二:从 Dockerfile 构建
build:
context: ./app # 构建上下文
dockerfile: Dockerfile # Dockerfile 路径
args: # 构建参数
VERSION: "1.0"
端口映射
yaml
services:
web:
image: nginx
ports:
- "8080:80" # 宿主机:容器
- "8443:443"
- "127.0.0.1:9090:80" # 绑定特定 IP
环境变量
yaml
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: testdb
MYSQL_USER: myuser
MYSQL_PASSWORD: mypassword
env_file:
- .env # 从文件加载
数据卷
yaml
services:
db:
image: mysql:8.0
volumes:
- db-data:/var/lib/mysql # 命名卷
- ./config:/etc/mysql/conf.d # 绑定挂载
- type: bind
source: ./logs
target: /var/log/mysql
read_only: true
volumes:
db-data: # 声明命名卷
网络配置
yaml
services:
web:
image: nginx
networks:
- frontend
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
依赖管理
yaml
services:
web:
image: myapp
depends_on:
- db
- redis
db:
image: mysql:8.0
redis:
image: redis:alpine
注意 :depends_on 只控制启动顺序,不等待服务就绪。可以使用健康检查:
yaml
services:
web:
image: myapp
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
资源限制
yaml
services:
web:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
重启策略
yaml
services:
web:
image: myapp
restart: always # 总是重启
# restart: on-failure # 失败时重启
# restart: unless-stopped # 除非手动停止
命令覆盖
yaml
services:
web:
image: nginx
command: nginx -g "daemon off;"
entrypoint: ["/docker-entrypoint.sh"]
四、常用命令
4.1 服务管理
bash
# 启动所有服务
docker compose up -d
# 启动指定服务
docker compose up -d web db
# 停止所有服务
docker compose stop
# 停止并删除容器、网络
docker compose down
# 停止并删除容器、网络、卷
docker compose down -v
# 重启服务
docker compose restart
# 暂停服务
docker compose pause
# 恢复暂停的服务
docker compose unpause
4.2 查看状态
bash
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs
docker compose logs -f
docker compose logs web # 指定服务
# 查看服务进程
docker compose top
# 查看资源使用
docker compose stats
4.3 进入容器
bash
# 在运行中的服务执行命令
docker compose exec web bash
docker compose exec db mysql -uroot -p
# 列出服务
docker compose ps --services
4.4 构建与更新
bash
# 构建镜像
docker compose build
# 构建并启动
docker compose up -d --build
# 更新镜像并重启
docker compose pull
docker compose up -d
# 不使用缓存重新构建
docker compose build --no-cache
4.5 扩缩容
bash
# 扩展服务副本数
docker compose up -d --scale web=3
# 查看副本状态
docker compose ps
五、实战示例
5.1 Spring Boot + MySQL + Redis
yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/zoodb
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root123
SPRING_REDIS_HOST: redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend
restart: unless-stopped
db:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: zoodb
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
restart: unless-stopped
volumes:
mysql-data:
redis-data:
networks:
backend:
driver: bridge
5.2 WordPress + MySQL
yaml
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: wp_pass
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress-data:/var/www/html
depends_on:
- db
restart: unless-stopped
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp_user
MYSQL_PASSWORD: wp_pass
MYSQL_ROOT_PASSWORD: root_pass
volumes:
- db-data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress-data:
db-data:
5.3 Nginx 反向代理 + 多服务
yaml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- app1
- app2
networks:
- frontend
app1:
image: myapp1:latest
networks:
- frontend
- backend
app2:
image: myapp2:latest
networks:
- frontend
- backend
db:
image: mysql:8.0
networks:
- backend
networks:
frontend:
backend:
六、环境变量与 .env 文件
6.1 使用 .env 文件
bash
# .env 文件
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=zoodb
APP_PORT=8080
yaml
# docker-compose.yml
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
6.2 变量优先级
- 命令行
-e参数 - Shell 环境变量
- .env 文件
- docker-compose.yml 中的 environment
七、最佳实践
7.1 安全建议
- 不要在 compose 文件中硬编码密码,使用
.env文件或 secrets - 限制端口暴露范围,使用
127.0.0.1:port:port - 使用健康检查确保服务就绪
- 定期更新镜像版本
7.2 性能优化
- 使用命名卷而非绑定挂载
- 合理设置资源限制
- 使用 Alpine 镜像减小体积
- 利用构建缓存
7.3 目录结构建议
project/
├── docker-compose.yml
├── .env
├── app/
│ ├── Dockerfile
│ └── src/
├── nginx/
│ └── nginx.conf
└── mysql/
└── init.sql
八、面试高频题
Q1:docker-compose 中的 depends_on 有什么作用?有什么局限?
A:depends_on 控制服务的启动顺序,确保依赖的服务先启动。但局限是它只等待容器启动,不等待服务就绪。例如 MySQL 容器启动了但还没准备好接受连接。解决方案是使用健康检查配合 condition: service_healthy。
Q2:Compose 文件中如何管理多个环境(开发、测试、生产)?
A:可以使用多个 compose 文件叠加。基础文件 docker-compose.yml 定义通用配置,环境文件如 docker-compose.prod.yml 覆盖特定配置。使用 docker compose -f docker-compose.yml -f docker-compose.prod.yml up 启动。也可以用 .env 文件和环境变量区分。
Q3:如何在 Compose 中实现服务间的负载均衡?
A:使用 scale 参数扩展服务副本:docker compose up -d --scale web=3。然后在 Nginx 等反向代理中配置上游服务器列表。也可以使用 Docker Swarm 的内置负载均衡。
至此,Docker 系列三篇博客全部完成!🎉