定义:
Docker Compose = 多容器应用编排工具
就像: 指挥家指挥整个乐队演奏
核心功能:
├─ 定义多容器应用架构
├─ 一键启动/停止应用
├─ 管理服务依赖关系
├─ 配置网络和数据卷
└─ 环境变量管理
应用场景:
├─ 开发环境快速搭建
├─ 自动化测试环境
├─ CI/CD流水线
└─ 单机部署应用
东巴文理解:
传统方式部署多容器应用:
├─ 手动创建网络
├─ 手动创建数据卷
├─ 手动启动多个容器
├─ 手动配置容器连接
└─ 容易出错,难以管理
使用Docker Compose:
├─ 编写docker-compose.yml文件
├─ 一键启动所有服务
├─ 自动管理依赖关系
├─ 自动配置网络和数据卷
└─ 简单高效,易于维护
架构图:
┌─────────────────────────────────────────┐
│ Docker Compose架构 │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ docker-compose.yml │ │
│ │ (应用配置文件) │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────┐ │
│ │ Docker Compose CLI │ │
│ │ (命令行工具) │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────┐ │
│ │ Docker Engine │ │
│ │ (Docker引擎) │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────┐ │
│ │ 多容器应用 │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │ Web │ │ API │ │ DB │ │ │
│ │ └──────┘ └──────┘ └──────┘ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
Linux安装:
# 下载Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
# 输出
Docker Compose version v2.20.0
Windows和macOS:
Docker Desktop for Windows和macOS
已内置Docker Compose,无需单独安装
验证:
docker-compose --version
版本说明:
Compose V1:
├─ 使用Python编写
├─ 命令: docker-compose
├─ 已停止维护
└─ 不推荐使用
Compose V2:
├─ 使用Go编写
├─ 命令: docker compose (注意空格)
├─ 性能更好
└─ 推荐使用
兼容性:
├─ V2兼容V1命令
├─ 推荐使用V2
└─ 本教程使用V2
docker-compose.yml:
# Compose文件版本
version: '3.8'
# 服务定义
services:
web:
image: nginx:latest
ports:
- "8080:80"
networks:
- frontend
api:
image: myapi:latest
ports:
- "3000:3000"
networks:
- frontend
- backend
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root123
volumes:
- db_data:/var/lib/mysql
networks:
- backend
# 网络定义
networks:
frontend:
backend:
# 数据卷定义
volumes:
db_data:
结构说明:
docker-compose.yml结构:
├─ version: Compose文件版本
├─ services: 服务定义(必需)
├─ networks: 网络定义(可选)
├─ volumes: 数据卷定义(可选)
├─ configs: 配置定义(可选)
└─ secrets: 密钥定义(可选)
文件要求:
├─ 使用YAML格式
├─ 缩进使用空格(不用Tab)
├─ 文件名通常为docker-compose.yml
└─ 支持环境变量替换
版本对应关系:
version: '3.8' # 推荐
├─ 支持Docker Engine 19.03.0+
├─ 支持所有特性
└─ 生产环境推荐
version: '3.0'
├─ 支持Docker Engine 1.13.0+
├─ 基本特性
└─ 兼容性好
version: '2.4'
├─ 支持Docker Engine 17.06.0+
├─ 不支持Swarm模式
└─ 单机部署
镜像配置:
services:
# 使用已有镜像
web:
image: nginx:latest
# 使用本地构建
app:
build: .
# 使用指定Dockerfile
api:
build:
context: ./api
dockerfile: Dockerfile.dev
# 使用镜像仓库
db:
image: mysql:5.7
容器配置:
services:
web:
image: nginx:latest
# 容器名称
container_name: mynginx
# 主机名
hostname: web-server
# 重启策略
restart: always
# 环境变量
environment:
- ENV=production
- DEBUG=false
# 环境变量文件
env_file:
- .env
- .env.prod
端口映射:
services:
web:
image: nginx:latest
ports:
# 短语法
- "8080:80"
- "443:443"
# 长语法
- target: 80
published: 8080
protocol: tcp
mode: host
端口说明:
端口映射格式:
"主机端口:容器端口"
短语法:
- "8080:80" # 映射TCP端口
- "8080:80/tcp" # 明确指定TCP
- "8080:80/udp" # 映射UDP端口
- "8080-8090:80-90" # 端口范围
长语法:
target: 容器端口
published: 主机端口
protocol: tcp/udp
mode: host(单机)/ingress(Swarm)
网络连接:
services:
web:
image: nginx:latest
networks:
- frontend
# 指定IP地址
networks:
frontend:
ipv4_address: 172.20.0.100
networks:
frontend:
ipam:
config:
- subnet: 172.20.0.0/16
网络配置:
networks:
# 默认网络
frontend:
# 自定义网络
backend:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# 使用已存在的网络
external:
external: true
name: my-existing-network
数据卷挂载:
services:
web:
image: nginx:latest
volumes:
# 命名卷
- web_data:/usr/share/nginx/html
# 绑定挂载
- ./html:/usr/share/nginx/html
# 匿名卷
- /usr/share/nginx/html
# 只读挂载
- ./config:/etc/nginx/conf.d:ro
volumes:
web_data:
driver: local
数据卷配置:
volumes:
# 命名卷
web_data:
# 指定驱动
db_data:
driver: local
driver_opts:
type: none
device: /data/db
o: bind
# 使用已存在的卷
existing_data:
external: true
name: my-existing-volume
服务依赖:
services:
web:
image: nginx:latest
depends_on:
- api
- db
api:
image: myapi:latest
depends_on:
- db
db:
image: mysql:5.7
依赖条件:
services:
api:
image: myapi:latest
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: mysql:5.7
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
docker compose up:
# 前台启动
docker compose up
# 后台启动
docker compose up -d
# 构建后启动
docker compose up --build
# 强制重新创建容器
docker compose up --force-recreate
# 不启动依赖服务
docker compose up --no-deps web
# 指定项目名称
docker compose -p myproject up -d
# 指定配置文件
docker compose -f docker-compose.prod.yml up -d
启动流程:
docker compose up执行流程:
├─ 读取docker-compose.yml文件
├─ 创建网络和数据卷
├─ 拉取或构建镜像
├─ 创建容器
├─ 启动容器
└─ 显示日志(前台模式)
docker compose down:
# 停止并删除容器
docker compose down
# 同时删除数据卷
docker compose down -v
# 同时删除镜像
docker compose down --rmi all
# 同时删除网络
docker compose down --remove-orphans
# 停止服务(不删除)
docker compose stop
# 启动已停止的服务
docker compose start
# 重启服务
docker compose restart
docker compose ps:
# 查看服务状态
docker compose ps
# 输出
NAME COMMAND SERVICE STATUS PORTS
myproject-web-1 "/docker-entrypoint.…" web running 0.0.0.0:8080->80/tcp
myproject-api-1 "node app.js" api running 0.0.0.0:3000->3000/tcp
myproject-db-1 "docker-entrypoint.s…" db running 3306/tcp
# 查看所有容器(包括停止的)
docker compose ps -a
docker compose logs:
# 查看所有服务日志
docker compose logs
# 查看指定服务日志
docker compose logs web
# 实时查看日志
docker compose logs -f
# 查看最后100行日志
docker compose logs --tail=100
# 查看带时间戳的日志
docker compose logs -t
docker compose exec:
# 进入容器
docker compose exec web bash
# 以root用户进入
docker compose exec -u root web bash
# 执行单个命令
docker compose exec web ls /app
# 指定工作目录
docker compose exec -w /app web ls
docker compose run:
# 运行一次性命令
docker compose run web ping google.com
# 运行交互式命令
docker compose run web bash
# 不启动依赖服务
docker compose run --no-deps web bash
# 删除运行后的容器
docker compose run --rm web ls
docker compose config:
# 验证配置文件
docker compose config
# 查看完整配置
docker compose config
# 查看服务名称
docker compose config --services
# 查看数据卷名称
docker compose config --volumes
docker compose images:
# 查看服务使用的镜像
docker compose images
# 输出
Container Repository Tag Image Id Size
myproject-web-1 nginx latest a1b2c3d4e5f6 142MB
myproject-api-1 myapi latest b2c3d4e5f6a7 120MB
myproject-db-1 mysql 5.7 c3d4e5f6a7b8 448MB
docker compose top:
# 查看容器进程
docker compose top
# 输出
myproject-web-1
UID PID PPID C STIME TTY TIME CMD
root 12345 12340 0 10:00 ? 00:00:00 nginx: master process nginx-
101 12346 12345 0 10:00 ? 00:00:00 nginx: worker process
.env文件:
# .env文件
# 数据库配置
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=mydb
MYSQL_USER=myuser
MYSQL_PASSWORD=mypassword
# 应用配置
APP_ENV=production
APP_DEBUG=false
APP_PORT=3000
# 端口配置
WEB_PORT=8080
API_PORT=3000
DB_PORT=3306
使用环境变量:
# docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "${WEB_PORT}:80"
api:
image: myapi:latest
environment:
- APP_ENV=${APP_ENV}
- APP_DEBUG=${APP_DEBUG}
ports:
- "${API_PORT}:3000"
db:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
ports:
- "${DB_PORT}:3306"
优先级顺序:
环境变量优先级(从高到低):
1. Shell环境变量
2. docker compose命令行参数
3. .env文件
4. docker-compose.yml中的默认值
示例:
# Shell环境变量
export MYSQL_ROOT_PASSWORD=newpassword
docker compose up -d
# 使用newpassword
# 命令行参数
MYSQL_ROOT_PASSWORD=cmdpassword docker compose up -d
# 使用cmdpassword
# .env文件
MYSQL_ROOT_PASSWORD=envpassword
docker compose up -d
# 使用envpassword
开发环境:
# docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
api:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
volumes:
- .:/app
生产环境:
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
restart: always
api:
image: myregistry.com/myapi:latest
ports:
- "3000:3000"
environment:
- NODE_ENV=production
restart: always
使用方法:
# 开发环境
docker compose up -d
# 生产环境
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 或使用环境变量
export COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml
docker compose up -d
多个环境变量文件:
# .env.development
APP_ENV=development
DEBUG=true
# .env.production
APP_ENV=production
DEBUG=false
# .env.test
APP_ENV=test
DEBUG=true
使用方法:
# 开发环境
docker compose --env-file .env.development up -d
# 生产环境
docker compose --env-file .env.production up -d
# 测试环境
docker compose --env-file .env.test up -d
docker-compose.yml:
version: '3.8'
services:
# WordPress服务
wordpress:
image: wordpress:latest
container_name: wordpress
restart: always
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
networks:
- wordpress-net
depends_on:
- db
# MySQL数据库
db:
image: mysql:5.7
container_name: wordpress-db
restart: always
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db_data:/var/lib/mysql
networks:
- wordpress-net
# 数据卷
volumes:
wordpress_data:
db_data:
# 网络
networks:
wordpress-net:
启动服务:
# 启动WordPress
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f
# 访问WordPress
# http://localhost:8080
docker-compose.yml:
version: '3.8'
services:
# 前端服务
frontend:
build: ./frontend
container_name: frontend
restart: always
ports:
- "80:80"
networks:
- frontend-net
depends_on:
- backend
# 后端服务
backend:
build: ./backend
container_name: backend
restart: always
ports:
- "3000:3000"
environment:
- DB_HOST=db
- DB_PORT=3306
- DB_NAME=myapp
- DB_USER=root
- DB_PASSWORD=root123
- REDIS_HOST=redis
- REDIS_PORT=6379
networks:
- frontend-net
- backend-net
depends_on:
- db
- redis
# 数据库服务
db:
image: mysql:5.7
container_name: mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=myapp
volumes:
- db_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- backend-net
# 缓存服务
redis:
image: redis:alpine
container_name: redis
restart: always
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- backend-net
# 数据卷
volumes:
db_data:
redis_data:
# 网络
networks:
frontend-net:
backend-net:
项目结构:
myapp/
├── docker-compose.yml
├── frontend/
│ ├── Dockerfile
│ └── src/
├── backend/
│ ├── Dockerfile
│ └── src/
└── init.sql
启动服务:
# 构建并启动
docker compose up --build -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f backend
# 扩展后端服务
docker compose up -d --scale backend=3
Compose核心概念:
├─ 项目(Project): 一组关联的服务
├─ 服务(Service): 应用的容器
├─ 网络(Network): 服务间通信
├─ 数据卷(Volume): 数据持久化
└─ 配置(Config): 应用配置
Compose文件结构:
├─ version: 文件版本
├─ services: 服务定义
├─ networks: 网络定义
├─ volumes: 数据卷定义
├─ configs: 配置定义
└─ secrets: 密钥定义
服务管理:
├─ docker compose up: 启动服务
├─ docker compose down: 停止并删除服务
├─ docker compose start: 启动服务
├─ docker compose stop: 停止服务
├─ docker compose restart: 重启服务
└─ docker compose pause/unpause: 暂停/恢复服务
服务查看:
├─ docker compose ps: 查看服务状态
├─ docker compose logs: 查看日志
├─ docker compose top: 查看进程
├─ docker compose images: 查看镜像
└─ docker compose config: 验证配置
服务操作:
├─ docker compose exec: 在容器中执行命令
├─ docker compose run: 运行一次性命令
├─ docker compose build: 构建镜像
└─ docker compose pull: 拉取镜像
文件组织:
✅ 使用版本控制管理配置文件
✅ 使用环境变量管理敏感信息
✅ 使用多配置文件管理多环境
✅ 合理命名服务和数据卷
服务配置:
✅ 设置合理的重启策略
✅ 配置健康检查
✅ 设置资源限制
✅ 使用依赖管理
网络和存储:
✅ 使用自定义网络
✅ 使用命名卷持久化数据
✅ 合理配置网络隔离
✅ 定期备份数据
构建优化:
✅ 使用多阶段构建
✅ 优化构建缓存
✅ 减小镜像大小
✅ 使用.dockerignore
运行优化:
✅ 设置资源限制
✅ 使用健康检查
✅ 优化日志配置
✅ 监控服务状态
下一章: Docker Compose进阶
将学习:
基本使用: 创建一个docker-compose.yml文件,启动一个nginx服务,映射端口8080:80,并验证访问。
多服务编排: 创建一个包含nginx和redis两个服务的docker-compose.yml文件,nginx使用自定义配置,redis设置密码。
数据持久化: 创建一个MySQL服务的docker-compose.yml文件,使用数据卷持久化数据,插入测试数据后删除容器,重新创建验证数据是否保留。
环境变量: 创建一个使用环境变量的docker-compose.yml文件,包含多个服务,使用.env文件管理配置,并支持多环境部署。
服务依赖: 创建一个三层架构应用的docker-compose.yml文件,包含前端、后端、数据库,配置服务依赖和健康检查。
网络隔离: 创建一个包含多个网络的docker-compose.yml文件,实现前端、后端、数据库的网络隔离。
完整应用: 为一个博客系统设计docker-compose.yml文件,要求:
多环境部署: 为一个微服务应用设计多环境部署方案,要求: