Docker Compose
核心知识点
1. Docker Compose 概述
1.1 什么是 Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过 YAML 文件配置应用的服务,然后使用一个命令创建并启动所有服务。
1.2 Compose 工作流程
┌─────────────────────────────────────────────────────────────┐
│ Docker Compose 工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 编写 docker-compose.yml │
│ ↓ │
│ 2. 运行 docker-compose up │
│ ↓ │
│ 3. 创建网络和数据卷 │
│ ↓ │
│ 4. 启动所有服务容器 │
│ ↓ │
│ 5. 应用运行中 │
│ │
└─────────────────────────────────────────────────────────────┘1.3 安装 Docker Compose
# 在 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 V2(集成在 Docker CLI 中)
docker compose version2. docker-compose.yml 基础
2.1 基本结构
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password2.2 常用指令
| 指令 | 说明 | 示例 |
|---|---|---|
image |
指定镜像 | image: nginx:latest |
build |
构建镜像 | build: ./app |
ports |
端口映射 | ports: - "80:80" |
volumes |
数据卷挂载 | volumes: - data:/app |
environment |
环境变量 | environment: - DEBUG=1 |
depends_on |
服务依赖 | depends_on: - db |
networks |
网络配置 | networks: - frontend |
restart |
重启策略 | restart: always |
3. 服务配置
3.1 镜像与构建
version: '3.8'
services:
# 使用现有镜像
web:
image: nginx:alpine
ports:
- "80:80"
# 从 Dockerfile 构建
app:
build: ./app
ports:
- "3000:3000"
# 使用构建参数
custom-app:
build:
context: ./app
dockerfile: Dockerfile.prod
args:
VERSION: "1.0"
ports:
- "3000:3000"3.2 端口与网络
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80" # 主机端口:容器端口
- "443:443"
- "8080-8090:8080-8090" # 端口范围
app:
image: node:16-alpine
networks:
- frontend
- backend
networks:
frontend:
backend:3.3 环境变量
version: '3.8'
services:
web:
image: nginx:latest
environment:
- NODE_ENV=production
- DEBUG=false
- API_URL=http://api:3000
# 使用 .env 文件
app:
image: node:16-alpine
env_file:
- .env
- .env.local
environment:
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}3.4 数据卷
version: '3.8'
services:
db:
image: mysql:5.7
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- /host/path:/container/path:ro
app:
image: node:16-alpine
volumes:
- ./app:/app
- node_modules:/app/node_modules
volumes:
db-data:
node_modules:4. 服务依赖与编排
4.1 服务依赖
version: '3.8'
services:
web:
image: nginx:latest
depends_on:
- app
app:
image: node:16-alpine
depends_on:
- db
environment:
DB_HOST: db
DB_PORT: 3306
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: myapp4.2 健康检查
version: '3.8'
services:
web:
image: nginx:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
app:
image: node:16-alpine
depends_on:
web:
condition: service_healthy5. 常用命令
5.1 启动与停止
# 启动所有服务
docker-compose up
# 后台启动
docker-compose up -d
# 启动特定服务
docker-compose up web db
# 停止所有服务
docker-compose stop
# 停止并删除容器
docker-compose down
# 停止并删除容器、网络、数据卷
docker-compose down -v5.2 查看服务状态
# 查看运行中的服务
docker-compose ps
# 查看服务日志
docker-compose logs
# 查看特定服务的日志
docker-compose logs web
# 实时跟踪日志
docker-compose logs -f
# 查看服务详细信息
docker-compose config5.3 服务管理
# 重启服务
docker-compose restart
# 重启特定服务
docker-compose restart web
# 重新构建服务
docker-compose build
# 重新构建并启动
docker-compose up --build
# 拉取最新镜像
docker-compose pull
# 扩展服务
docker-compose up -d --scale web=36. 高级配置
6.1 多文件配置
# docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
app:
extends:
file: docker-compose.common.yml
service: app
# docker-compose.common.yml
version: '3.8'
services:
app:
image: node:16-alpine
environment:
NODE_ENV: production6.2 生产环境配置
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./ssl:/etc/nginx/ssl
restart: always
app:
image: myapp:latest
environment:
NODE_ENV: production
DEBUG: "false"
restart: always
deploy:
replicas: 3
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
# 使用生产配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d实用案例分析
案例 1:Web 应用与数据库
场景描述
部署一个包含 Nginx、Node.js 和 MySQL 的完整 Web 应用。
docker-compose.yml
version: '3.8'
services:
# Nginx Web 服务器
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./app/dist:/usr/share/nginx/html
depends_on:
- app
restart: always
# Node.js 应用
app:
build: ./app
ports:
- "3000:3000"
environment:
NODE_ENV: production
DB_HOST: mysql
DB_USER: myapp
DB_PASSWORD: password
DB_NAME: myapp
depends_on:
- mysql
restart: always
# MySQL 数据库
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp
MYSQL_USER: myapp
MYSQL_PASSWORD: password
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
volumes:
mysql-data:操作步骤
# 1. 创建项目目录
mkdir ~/my-web-app
cd ~/my-web-app
# 2. 创建目录结构
mkdir -p app nginx
# 3. 创建 docker-compose.yml 文件
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./app/dist:/usr/share/nginx/html
depends_on:
- app
restart: always
app:
build: ./app
ports:
- "3000:3000"
environment:
NODE_ENV: production
DB_HOST: mysql
DB_USER: myapp
DB_PASSWORD: password
DB_NAME: myapp
depends_on:
- mysql
restart: always
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp
MYSQL_USER: myapp
MYSQL_PASSWORD: password
volumes:
- mysql-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: always
volumes:
mysql-data:
EOF
# 4. 创建 Nginx 配置
cat > nginx/nginx.conf << 'EOF'
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://app:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
EOF
# 5. 创建应用 Dockerfile
cat > app/Dockerfile << 'EOF'
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
RUN npm run build
CMD ["npm", "start"]
EOF
# 6. 创建 package.json
cat > app/package.json << 'EOF'
{
"name": "my-web-app",
"version": "1.0.0",
"scripts": {
"start": "node server.js",
"build": "echo 'Build complete'"
},
"dependencies": {
"express": "^4.18.0",
"mysql2": "^3.0.0"
}
}
EOF
# 7. 创建应用代码
cat > app/server.js << 'EOF'
const express = require('express');
const mysql = require('mysql2/promise');
const app = express();
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
app.get('/', async (req, res) => {
try {
const [rows] = await pool.query('SELECT NOW() as now');
res.json({ message: 'Hello from Docker!', time: rows[0].now });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
EOF
# 8. 创建初始化 SQL
cat > init.sql << 'EOF'
CREATE TABLE IF NOT EXISTS test (
id INT AUTO_INCREMENT PRIMARY KEY,
message VARCHAR(255)
);
EOF
# 9. 启动服务
docker-compose up -d
# 10. 查看服务状态
docker-compose ps
# 11. 查看日志
docker-compose logs
# 12. 测试访问
curl http://localhost
# 13. 清理
docker-compose down -v案例 2:开发环境配置
场景描述
配置开发环境,支持代码热重载和调试。
docker-compose.dev.yml
version: '3.8'
services:
# 应用服务(开发模式)
app:
build:
context: ./app
dockerfile: Dockerfile.dev
volumes:
- ./app:/app
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229" # 调试端口
environment:
NODE_ENV: development
DEBUG: myapp:*
command: npm run dev
# 数据库服务
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp_dev
ports:
- "3306:3306"
volumes:
- db-dev-data:/var/lib/mysql
# Redis 缓存
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- redis-dev-data:/data
volumes:
db-dev-data:
redis-dev-data:操作步骤
# 1. 创建开发配置
cat > docker-compose.dev.yml << 'EOF'
version: '3.8'
services:
app:
build:
context: ./app
dockerfile: Dockerfile.dev
volumes:
- ./app:/app
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229"
environment:
NODE_ENV: development
DEBUG: myapp:*
command: npm run dev
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp_dev
ports:
- "3306:3306"
volumes:
- db-dev-data:/var/lib/mysql
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- redis-dev-data:/data
volumes:
db-dev-data:
redis-dev-data:
EOF
# 2. 创建开发 Dockerfile
cat > app/Dockerfile.dev << 'EOF'
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
EOF
# 3. 更新 package.json
cat > app/package.json << 'EOF'
{
"name": "my-web-app",
"version": "1.0.0",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"express": "^4.18.0",
"mysql2": "^3.0.0"
},
"devDependencies": {
"nodemon": "^3.0.0"
}
}
EOF
# 4. 启动开发环境
docker-compose -f docker-compose.dev.yml up -d
# 5. 查看日志
docker-compose -f docker-compose.dev.yml logs -f app
# 6. 测试代码热重载
# 修改 app/server.js 文件,观察日志输出
# 7. 清理
docker-compose -f docker-compose.dev.yml down -v案例 3:服务扩展与负载均衡
场景描述
扩展应用服务,实现负载均衡。
docker-compose.yml
version: '3.8'
services:
# 负载均衡器
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
# 应用服务(可扩展)
app:
image: myapp:latest
environment:
NODE_ENV: production
deploy:
replicas: 3
resources:
limits:
cpus: '0.50'
memory: 256Mnginx 配置
upstream backend {
least_conn;
server app:3000;
server app:3000;
server app:3000;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}操作步骤
# 1. 创建负载均衡配置
mkdir -p nginx
cat > nginx/nginx.conf << 'EOF'
upstream backend {
least_conn;
server app:3000;
server app:3000;
server app:3000;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
# 2. 创建 docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
app:
image: nginx:alpine
environment:
NODE_ENV: production
EOF
# 3. 启动服务
docker-compose up -d
# 4. 扩展应用服务
docker-compose up -d --scale app=3
# 5. 查看服务状态
docker-compose ps
# 6. 测试负载均衡
for i in {1..10}; do
curl -s http://localhost | grep -o "Welcome"
done
# 7. 清理
docker-compose down最佳实践
使用版本控制:将 docker-compose.yml 文件纳入版本控制。
分离配置文件:使用多个配置文件管理不同环境。
# 开发环境
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d- 使用 .env 文件:管理敏感信息。
# .env 文件
DB_PASSWORD=secret
API_KEY=your-api-key
# docker-compose.yml
services:
app:
environment:
DB_PASSWORD: ${DB_PASSWORD}
API_KEY: ${API_KEY}- 合理设置重启策略:确保服务高可用。
services:
app:
restart: unless-stopped- 使用健康检查:确保服务正常运行。
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 3总结
本教程详细介绍了 Docker Compose 的使用方法,包括 docker-compose.yml 文件的编写、服务配置、常用命令等。通过实际案例,我们学习了如何部署多容器应用、配置开发环境以及实现负载均衡。掌握这些技能后,可以高效地编排和管理多容器 Docker 应用。