Docker Compose

Docker Compose 的核心概念:services、networks、volumes、depends_on、environment、profiles。

#type / howto #status / growing #tech / ops #resource / docker

[!info] related notes

Docker Compose

一句话定义

Docker Compose 用一个 YAML 文件定义和管理多容器应用,一条命令启动整个服务栈。

基本结构

# docker-compose.yml
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
    depends_on:
      - db
      - redis

  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

services

每个 service 是一个容器的配置:

services:
  app:
    # 从 Dockerfile 构建
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production

    # 或直接使用镜像
    image: node:20-alpine

    # 端口映射(宿主机:容器)
    ports:
      - "8080:3000"
      - "9229:9229"  # 调试端口

    # 环境变量
    environment:
      - NODE_ENV=production
    # 或从文件读取
    env_file:
      - .env
      - .env.production

    # 命令覆盖
    command: ["node", "server.js"]

    # 工作目录
    working_dir: /app

    # 重启策略
    restart: unless-stopped

    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

networks

services:
  web:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16
  • 默认所有 service 在同一个网络,可以用服务名互相访问
  • 自定义网络可以隔离服务间的通信

volumes

services:
  db:
    volumes:
      # 命名卷(持久化,Docker 管理)
      - postgres_data:/var/lib/postgresql/data
      # 绑定挂载(宿主机目录)
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
      # 只读挂载
      - ./config:/etc/app/config:ro

volumes:
  postgres_data:  # 声明命名卷
  • 命名卷:Docker 管理生命周期,适合数据库数据
  • 绑定挂载:直接映射宿主机目录,适合开发时热重载

depends_on

services:
  web:
    depends_on:
      db:
        condition: service_healthy  # 等 db 健康检查通过
      redis:
        condition: service_started  # 只等 redis 启动

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      timeout: 5s
      retries: 5
  • service_started:容器启动即可(默认)
  • service_healthy:健康检查通过才算就绪
  • service_completed_successfully:容器退出且退出码为 0

environment 与 env_file

services:
  app:
    # 直接定义
    environment:
      NODE_ENV: production
      DEBUG: "app:*"

    # 或从文件读取
    env_file:
      - .env
      - .env.local  # 优先级更高,覆盖 .env 中的同名变量

    # 也可以用列表语法
    environment:
      - NODE_ENV=production

.env 文件格式:

# .env
NODE_ENV=production
DATABASE_URL=postgres://user:pass@db:5432/mydb
REDIS_URL=redis://redis:6379

profiles

按需启动服务,避免启动所有容器:

services:
  web:
    image: node:20
    # 无 profile,默认启动

  db:
    image: postgres:16
    # 无 profile,默认启动

  debug-tools:
    image: busybox
    profiles:
      - debug      # 只在指定 profile 时启动

  monitoring:
    image: prometheus
    profiles:
      - monitoring

# 启动方式:
# docker compose up              -> 只启动 web 和 db
# docker compose --profile debug up -> 启动 web、db、debug-tools
# docker compose --profile debug --profile monitoring up -> 全部启动

常用命令

# 启动所有服务(后台)
docker compose up -d

# 查看运行中的服务
docker compose ps

# 查看日志
docker compose logs -f web  # 只看 web 的日志

# 停止并删除容器(保留卷)
docker compose down

# 停止并删除容器和卷
docker compose down -v

# 重建镜像并启动
docker compose up -d --build

# 进入容器
docker compose exec web sh

# 运行一次性命令
docker compose run --rm web npm test

常见误区

  • depends_on 不等服务就绪:需要 condition: service_healthy + healthcheck
  • 服务间通信用服务名:不是 localhost,是 dbredis 等服务名
  • volumes 声明在顶层:服务中引用的是顶层声明的命名卷
  • .envenvironment 的优先级:environment > .env.local > .env
  • restart: always 不适合开发:开发环境用 noon-failure
创建于 2026/5/27 更新于 2026/5/27