Docker Compose 快速入门
Docker Compose 是定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YAML 文件来配置应用程序的服务,然后使用一个简单的命令创建并启动所有服务。
目录
Compose 概述
1.1 什么是 Docker Compose
Docker Compose 是 Docker 官方提供的容器编排工具,主要特点:
Docker Compose 特点:
┌─────────────────────────────────────────┐
│ 1. 单一配置文件 │
│ - docker-compose.yml │
│ - 声明式服务定义 │
├─────────────────────────────────────────┤
│ 2. 一键启动/停止 │
│ - docker-compose up │
│ - docker-compose down │
├─────────────────────────────────────────┤
│ 3. 服务自动编排 │
│ - 自动处理依赖关系 │
│ - 自动创建网络和卷 │
├─────────────────────────────────────────┤
│ 4. 开发环境友好 │
│ - 代码热重载 │
│ - 环境变量管理 │
└─────────────────────────────────────────┘1.2 Compose 适用场景
| 场景 | 说明 |
|---|---|
| 开发环境 | 本地开发、调试 |
| 测试环境 | 自动化测试 |
| 单机部署 | 单主机生产环境 |
| CI/CD | 持续集成/部署 |
| 演示环境 | 快速搭建演示 |
1.3 Compose vs Swarm vs Kubernetes
| 特性 | Compose | Swarm | Kubernetes |
|---|---|---|---|
| 复杂度 | 低 | 中 | 高 |
| 多主机 | ❌ | ✅ | ✅ |
| 自动扩缩容 | ❌ | ✅ | ✅ |
| 服务发现 | 基础 | 完整 | 完整 |
| 适用场景 | 开发/测试 | 小型生产 | 大型生产 |
安装 Docker Compose
2.1 Docker Desktop
Docker Desktop 已包含 Docker Compose:
bash
# 验证安装
docker-compose --version
# 或
docker compose version2.2 Linux 安装
bash
# 下载 Docker Compose 插件
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 \
-o $DOCKER_CONFIG/cli-plugins/docker-compose
# 添加执行权限
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
# 验证安装
docker compose version2.3 独立安装(旧版本)
bash
# 下载
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
# 添加权限
chmod +x /usr/local/bin/docker-compose
# 创建软链接
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 验证
docker-compose --version第一个 Compose 应用
3.1 项目结构
my-compose-app/
├── docker-compose.yml
├── web/
│ ├── Dockerfile
│ ├── package.json
│ └── src/
│ └── index.js
└── README.md3.2 Web 应用代码
javascript
// web/src/index.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({
message: 'Hello from Docker Compose!',
timestamp: new Date().toISOString()
});
});
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});json
// web/package.json
{
"name": "web",
"version": "1.0.0",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}3.3 Dockerfile
dockerfile
# web/Dockerfile
FROM node:18-alpine
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm ci --only=production
# 复制应用代码
COPY src/ ./src/
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["npm", "start"]3.4 Compose 文件
yaml
# docker-compose.yml
version: '3.8'
services:
web:
build: ./web
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
volumes:
redis-data:3.5 启动应用
bash
# 进入项目目录
cd my-compose-app
# 启动服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 测试应用
curl http://localhost:3000核心概念
4.1 Services(服务)
服务是 Compose 应用的基本单元:
yaml
services:
# Web 服务
web:
image: nginx:alpine
ports:
- "80:80"
# 数据库服务
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
# 缓存服务
cache:
image: redis:7-alpine4.2 Networks(网络)
Compose 自动创建网络,服务间可以通过服务名通信:
yaml
services:
web:
image: nginx:alpine
networks:
- frontend
- backend
api:
image: myapi:latest
networks:
- backend
db:
image: postgres:15-alpine
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 无外部访问4.3 Volumes(卷)
数据持久化和共享:
yaml
services:
db:
image: postgres:15-alpine
volumes:
# 命名卷
- db-data:/var/lib/postgresql/data
# 绑定挂载
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
# 临时卷
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
volumes:
db-data:
driver: local4.4 环境变量
yaml
services:
web:
image: myapp:latest
environment:
# 直接设置
NODE_ENV: production
# 引用主机环境变量
API_KEY: ${API_KEY}
# 带默认值
PORT: ${PORT:-3000}
# 必需变量
DATABASE_URL: ${DATABASE_URL:?DATABASE_URL is required}
env_file:
- .env
- .env.local常用命令
5.1 生命周期管理
bash
# 启动服务
docker-compose up # 前台运行
docker-compose up -d # 后台运行
docker-compose up --build # 重新构建
docker-compose up --force-recreate # 强制重新创建
# 停止服务
docker-compose stop # 停止
docker-compose down # 停止并删除
docker-compose down -v # 同时删除卷
docker-compose down --rmi all # 同时删除镜像
# 重启服务
docker-compose restart # 重启所有
docker-compose restart web # 重启指定服务5.2 查看状态
bash
# 查看服务状态
docker-compose ps
docker-compose ps -q # 只显示 ID
# 查看日志
docker-compose logs # 所有服务
docker-compose logs web # 指定服务
docker-compose logs -f # 实时跟踪
docker-compose logs --tail 100 # 最后 100 行
# 查看进程
docker-compose top
# 查看事件
docker-compose events5.3 服务操作
bash
# 构建服务
docker-compose build # 构建所有
docker-compose build web # 构建指定服务
docker-compose build --no-cache # 不使用缓存
# 拉取镜像
docker-compose pull
# 推送镜像
docker-compose push
# 扩展服务
docker-compose up -d --scale web=3
# 在容器中执行命令
docker-compose exec web bash
docker-compose exec -T web ps aux
# 运行一次性命令
docker-compose run --rm web npm test5.4 配置管理
bash
# 验证配置
docker-compose config # 查看完整配置
docker-compose config -q # 只验证,不输出
# 查看环境变量
docker-compose config --environment实战示例
6.1 Web + API + 数据库
yaml
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
depends_on:
- api
networks:
- frontend
api:
build: ./api
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_USER=api
- DB_PASS=${DB_PASSWORD}
- REDIS_HOST=redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- frontend
- backend
restart: unless-stopped
db:
image: postgres:15-alpine
volumes:
- db-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
environment:
POSTGRES_USER: api
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U api -d app"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
networks:
- backend
volumes:
db-data:
redis-data:
networks:
frontend:
backend:
internal: true6.2 开发环境配置
yaml
# docker-compose.yml
version: '3.8'
services:
web:
build:
context: ./web
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./web:/app
- /app/node_modules
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
command: npm run dev
api:
build:
context: ./api
dockerfile: Dockerfile.dev
ports:
- "5000:5000"
volumes:
- ./api:/app
- /app/__pycache__
environment:
- FLASK_ENV=development
- FLASK_DEBUG=1
command: flask run --host=0.0.0.0 --reload
db:
image: postgres:15-alpine
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: app
volumes:
db-data:6.3 生产环境配置
yaml
# docker-compose.prod.yml
version: '3.8'
services:
web:
build:
context: ./web
dockerfile: Dockerfile
restart: always
deploy:
replicas: 2
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
api:
build:
context: ./api
dockerfile: Dockerfile
restart: always
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
db:
restart: always
deploy:
placement:
constraints:
- node.role == manager部署命令:
bash
# 生产部署
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 或使用环境变量
COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml docker-compose up -d