Skip to content

Docker Compose 快速入门

Docker Compose 是定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YAML 文件来配置应用程序的服务,然后使用一个简单的命令创建并启动所有服务。

目录

  1. Compose 概述
  2. 安装 Docker Compose
  3. 第一个 Compose 应用
  4. 核心概念
  5. 常用命令
  6. 实战示例

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

特性ComposeSwarmKubernetes
复杂度
多主机
自动扩缩容
服务发现基础完整完整
适用场景开发/测试小型生产大型生产

安装 Docker Compose

2.1 Docker Desktop

Docker Desktop 已包含 Docker Compose:

bash
# 验证安装
docker-compose --version
# 或
docker compose version

2.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 version

2.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.md

3.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-alpine

4.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: local

4.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 events

5.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 test

5.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: true

6.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

下一步

基于 MIT 许可发布