Docker: Docker Compose入门

最后更新:2026-08-26

5 条 docker run 命令变成 1 条 docker compose up——Compose 让多容器部署从手动操作变成声明式配置。

1. 你将学到


2. 一个开发者的真实故事

(1) 痛点:每次调试 5 条 docker run

Alice 每次调试都要手动敲 5 条 docker run 命令启动 Web/DB/Cache/Queue/Worker 四个容器——参数多、顺序不能错、环境变量容易打错。有一次她忘了加 --network app-net,花了 1 小时排查为什么 Web 连不上数据库。

(2) Docker Compose 声明式配置的解法

Bob 写了一个 docker-compose.yml,Alice 从此只需 docker compose up -d

YAML
# docker-compose.yml - One file defines everything
services:
  web:
    image: nginx:alpine
    ports: ["8080:80"]
    depends_on:
      - api
  api:
    build: .
    environment:
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
    volumes:
      - pg-data:/var/lib/postgresql/data

volumes:
  pg-data:

networks:
  default:
    name: app-net

(3) 收益:5 条命令→1 条命令

部署从 5 条命令 + 手动配置降到 1 条 docker compose up -d。新人 5 分钟就能跑起整个项目。


3. docker-compose.yml 结构

(1) 三大顶级字段

YAML
# docker-compose.yml structure
services:    # Container definitions (required)
  web:
    image: nginx:alpine

volumes:     # Named volume declarations (optional)
  pg-data:

networks:    # Custom network declarations (optional)
  app-net:

(2) docker run vs docker compose 对比

维度 docker run docker compose
定义方式 命令行参数 YAML 文件
可复现性 低(依赖操作者记忆) 高(文件可提交 Git)
多容器 多条命令 一个文件
网络/卷 手动创建 自动声明式管理
环境变量 多个 -e 参数 env_file 或 environment 块
版本控制 ✅ YAML 可 git diff

4. Services 配置详解

(1) 常用服务字段

字段 作用 示例
image 使用已有镜像 image: nginx:alpine
build 从 Dockerfile 构建 build: .build: { context: ., dockerfile: Dockerfile.prod }
ports 端口映射 ports: ["8080:80"]
environment 环境变量 environment: { POSTGRES_PASSWORD: secret }
env_file 从文件加载变量 env_file: .env
volumes 卷挂载 volumes: [pg-data:/var/lib/postgresql/data]
depends_on 启动依赖 depends_on: [db]
restart 重启策略 restart: unless-stopped
networks 指定网络 networks: [app-net]
healthcheck 健康检查 healthcheck: { test: ["CMD", "curl", "-f", "http://localhost/"] }

▶ 示例:编写最简 compose 文件(难度⭐)

YAML
# Minimal docker-compose.yml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
BASH
# Start with compose
docker compose up -d

# Verify
docker compose ps

5. 依赖控制:depends_on

(1) 三种等待策略

策略 语法 等待到 说明
started(默认) depends_on: [db] 容器启动 不保证服务就绪
healthy depends_on: { db: { condition: service_healthy } } 健康检查通过 ✅ 推荐生产使用
completed depends_on: { init: { condition: service_completed_successfully } } 容器成功退出 初始化任务

▶ 示例:depends_on + healthcheck 依赖控制(难度⭐⭐)

YAML
services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  api:
    build: .
    environment:
      DATABASE_URL: postgresql://postgres:secret@db:5432/myapp
    depends_on:
      db:
        condition: service_healthy

volumes:
  pg-data:
💡 提示: depends_on: [db](默认)只等 db 容器启动,不等 PostgreSQL 就绪。API 可能在 DB 未准备好时就尝试连接而失败。condition: service_healthy 确保 PostgreSQL 真正就绪后 API 才启动。


6. Volumes 和 Networks 声明

▶ 示例:声明卷和网络(难度⭐⭐)

YAML
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./src:/usr/share/nginx/html:ro    # Bind mount (read-only)
      - nginx-cache:/var/cache/nginx       # Named volume
    networks:
      - frontend
      - backend

  api:
    build: .
    networks:
      - backend
      - database

  db:
    image: postgres:15-alpine
    volumes:
      - pg-data:/var/lib/postgresql/data
    networks:
      - database

volumes:
  pg-data:
  nginx-cache:

networks:
  frontend:
  backend:
  database:
    internal: true   # No external access

7. 环境变量管理

(1) 三种方式对比

方式 语法 适用场景
environment 块 environment: { KEY: VALUE } 少量固定变量
env_file env_file: .env 多变量/敏感信息
shell 变量 environment: { KEY: ${VAR} } 动态配置

▶ 示例:env_file 和变量替换(难度⭐⭐)

YAML
# docker-compose.yml with variable substitution
services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD:-defaultsecret}
      POSTGRES_DB: ${DB_NAME:-myapp}
    env_file:
      - .env.db

  api:
    build: .
    environment:
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD:-defaultsecret}@db:5432/${DB_NAME:-myapp}
BASH
# .env.db
POSTGRES_USER=appuser
POSTGRES_PASSWORD=secret123
📌 重点: ${VAR:-default} 语法:如果 VAR 未设置,使用 default 值。这样 compose 文件有默认值,生产环境用 .env 文件覆盖。


8. Docker Compose 常用命令

命令 作用 示例
docker compose up -d 启动所有服务(后台) docker compose up -d
docker compose down 停止并删除所有容器/网络 docker compose down
docker compose down -v 同时删除卷 docker compose down -v
docker compose ps 查看服务状态 docker compose ps
docker compose logs 查看日志 docker compose logs -f api
docker compose exec 进入容器 docker compose exec api bash
docker compose build 重新构建镜像 docker compose build api
docker compose pull 拉取最新镜像 docker compose pull
docker compose config 验证并显示合并后的配置 docker compose config

▶ 示例:docker compose up -d 启动(难度⭐)

BASH
# Start all services in detached mode
docker compose up -d

# Follow logs from all services
docker compose logs -f

# Follow logs from a specific service
docker compose logs -f api

▶ 示例:docker compose exec 进入容器(难度⭐)

BASH
# Open shell in the api service container
docker compose exec api bash

# Run a one-off command
docker compose exec db psql -U postgres -d myapp

▶ 示例:docker compose down 清理(难度⭐)

BASH
# Stop and remove containers + networks
docker compose down

# Also remove named volumes (WARNING: deletes data)
docker compose down -v

# Also remove images
docker compose down --rmi all

9. 完整示例:WordPress + MySQL

YAML
# ============================================
# docker-compose.yml: WordPress + MySQL
# Features: volumes, networks, depends_on, healthcheck
# ============================================

services:
  wordpress:
    image: wordpress:6.4-php8.2-apache
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:-wppass123}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp-content:/var/www/html/wp-content
    depends_on:
      mysql:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - wp-net

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: ${DB_PASSWORD:-wppass123}
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - wp-net

volumes:
  mysql-data:
  wp-content:

networks:
  wp-net:
BASH
# Deploy
docker compose up -d

# Verify
docker compose ps
docker compose logs -f wordpress

# Access WordPress
# Open http://localhost:8080 in browser

# Clean up (keeps data)
docker compose down

# Clean up everything (deletes data)
docker compose down -v

❓ 常见问题

Q docker-compose.yml 用哪个版本?
A 新版 Docker Compose V2 不再需要 version 字段。直接从 services: 开始写即可。如果看到旧教程写 version: "3.8",可以删掉——V2 忽略它。
Q depends_on 能保证服务就绪吗?
A 默认 depends_on: [db] 只保证 db 容器启动,不保证 PostgreSQL 就绪。加 condition: service_healthy 才等健康检查通过。这是 Compose 新手最常见的坑——服务启动但依赖未就绪导致连接失败。
Q Compose 文件里的环境变量怎么管理?
A 三层管理:① docker-compose.yml 里的 environment 块(非敏感默认值);② .env 文件(环境特定值,不提交 Git);③ ${VAR:-default} 语法(给默认值兜底)。敏感密码不要写在 YAML 里,用 .env 文件 + .gitignore。
Q docker compose down 会删数据卷吗?
A 默认不删除。docker compose down 只删除容器和网络,Named Volume 保留。加 -v 才删除卷。生产环境不要用 down -v,只用 down
Q Compose 项目名有什么用?
A 项目名隔离不同 Compose 应用的资源。默认用当前目录名。docker compose -p myproject up 自定义项目名。同一台机器可以运行多个 Compose 项目,互不干扰。

📖 小节


📝 作业

  1. 基础题(难度⭐):为 Phase 1 的 LEMP 栈(Nginx+PHP+MySQL)编写 docker-compose.yml,用 docker compose up -d 启动。
  2. 进阶题(难度⭐⭐):在 compose 文件中添加 depends_on + healthcheck,确保 MySQL 就绪后 PHP-FPM 才启动。
  3. 挑战题(难度⭐⭐⭐):用 docker compose logs 排查一个启动失败的服务,分析日志找到根因并修复。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏