Skip to content

Docker Compose 实战指南 ​

当你的应用不再只有一个容器,而是由数据库、缓存、后端、前端等多个服务组成时,手写 docker run 参数变得不可维护。Docker Compose 用一个 YAML 文件描述所有服务,一条命令启动整个架构。

快速上手 ​

一个典型的 Web 应用 ​

yaml
version: "3.9"

services:
  db:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: appdb
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    ports:
      - "6379:6379"

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/appdb
      SPRING_REDIS_HOST: redis
    ports:
      - "8080:8080"

volumes:
  db_data:

常用命令 ​

bash
docker compose up -d            # 后台启动所有服务
docker compose up -d --build    # 重新构建镜像后启动
docker compose down             # 停止并移除容器(保留数据卷)
docker compose down -v          # 连同数据卷一起删除
docker compose ps               # 查看运行状态
docker compose logs -f backend  # 实时查看日志
docker compose exec db mysql -uroot -p  # 进入容器执行命令
docker compose restart redis    # 重启单个服务

核心概念 ​

网络(Networks) ​

Compose 默认创建一个 bridge 网络,服务之间用服务名作为主机名通信。后端可以直接用 db:3306 访问 MySQL,不需要 IP。

数据卷(Volumes) ​

持久化数据有三种方式:

  1. 命名卷:由 Docker 管理,适合数据库等持久数据
  2. 绑定挂载:映射宿主机路径,适合配置文件和开发热重载
  3. 匿名卷:不推荐,容器删除后难以管理

环境变量管理 ​

用 .env 文件集中管理,不要把密码硬编码在 YAML 里:

bash
# .env 文件(不要提交到 git!)
DB_ROOT_PASSWORD=super_secret_123
JWT_SECRET=your_jwt_secret
yaml
# docker-compose.yml 中引用
services:
  db:
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}

安全提示:把 .env 加入 .gitignore,提供 .env.example 作为模板。

健康检查(Healthcheck) ​

depends_on 默认只保证启动顺序,不保证服务就绪。加上 healthcheck + condition: service_healthy 可以实现「等待依赖就绪后再启动」。

生产环境最佳实践 ​

多阶段构建减小镜像体积 ​

dockerfile
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

资源限制 ​

yaml
services:
  backend:
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 1G

日志轮转 ​

防止日志文件无限增长撑爆磁盘:

yaml
services:
  backend:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

常见坑 ​

坑原因解决
服务启动报 Connection refuseddepends_on 不等就绪加 healthcheck + service_healthy
数据库数据丢失用了 down -v 或匿名卷用命名卷或绑定挂载
容器内连不上宿主机bridge 网络隔离用 host.docker.internal
构建慢每次都重装依赖利用 Docker 缓存层

小结 ​

Docker Compose 把多容器编排简化为一个 YAML 文件。掌握网络、数据卷、环境变量、健康检查四个核心概念,加上多阶段构建和日志轮转,就能应对大部分中小型项目的部署需求。

基于 VitePress 构建

总访问量 访客数