Docker Compose(容器编排)使用指南

Docker Compose(容器编排)使用指南

九月 05, 2025 次阅读

什么是 Docker Compose

docker-compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过使用 YAML 文件来配置应用程序的服务,用户可以使用单个命令来创建和启动所有服务,从而便利的管理复杂的应用程序架构。

docker-compose 中有两个非常重要的概念:

  • 服务(Service):服务是指在 Docker Compose 文件中定义的一个容器实例。每个服务通常对应于一个应用程序组件,例如数据库、缓存服务器或 Web 服务器。服务定义了容器的镜像、环境变量、端口映射、卷挂载等配置。
  • 项目(Project):项目是由一组相关的服务组成的集合。每个项目都有一个唯一的名称,通常是 Docker Compose 文件所在目录的名称。项目名称用于区分不同的应用程序实例,确保同一主机上可以运行多个独立的应用程序。项目默认是在 docker-compose.yml 文件中构建的,整个项目的生命周期由 Docker Compose 工具进行管理。

因此,通过 compose 可以方便管理多个服务实例,简化开发和部署流程。

compose structure

docker compose 就像一艘航母一样,有舰载机、防空导弹,这些也就是一个个的容器,彼此之间通过网络进行通信和协作,共同完成复杂的应用程序功能。

为什么要 Docker Compose

在微服务架构中,应用程序通常由多个独立的服务组成,每个服务都运行在自己的容器中。管理这些容器的生命周期、网络和存储等配置变得非常复杂。Docker Compose 提供了一种简单的方式来定义和管理这些多容器应用程序。

使用 Docker Compose 的主要优点包括:

  1. 简化配置:通过 YAML 文件集中管理所有服务的配置,避免了手动配置每个容器的繁琐过程。
  2. 一致性:确保在不同环境(如开发、测试和生产)中使用相同的配置,减少了环境差异带来的问题。
  3. 易于扩展:可以轻松添加、删除或修改服务,支持快速迭代和开发。
  4. 集中管理:通过一个命令(如 docker-compose up)启动或停止整个应用程序,简化了操作流程。
  5. 自定义服务启动顺序:可以通过配置文件指定服务的启动顺序,确保依赖关系正确处理。若通过手动部署,可能会因为服务启动顺序不合理导致服务启动失败。

使用 docker compose,可以大大提高开发和运维的效率,特别是在处理复杂的多容器应用程序时。毕竟,你也不想每次都手动启动和停止一个个的容器吧。

Docker Compose 的功能

使用 docker-compose.yml(默认是这个文件)来定义应用程序的服务和配置。然后,通过以下命令来管理应用程序的生命周期:

  1. 启动服务:使用 docker-compose up 命令启动所有服务。
  2. 停止服务:使用 docker-compose down 命令停止所有服务并清理资源。
  3. 查看日志:使用 docker-compose logs 命令查看所有服务的日志输出。
  4. 执行命令:使用 docker-compose exec 命令在指定服务的容器中执行命令。

Docker Compose 文件

目前官方支持两个大版本,Version 2 和 Version 3。Version 3 是目前推荐使用的版本,支持更多的功能和特性,Version 1 已经不再维护。下面对该文件的讲解基于 Version 3。


Docker Compose 文件的基本结构

docker-compose.yml 文件是 Docker Compose 的核心配置文件,它描述了应用需要的服务、网络、卷等。一个典型的 Compose 文件包含以下层次结构:

  • services:定义应用中的服务,每个服务相当于一个容器的配置。
  • volumes(可选):定义数据卷,方便服务之间共享数据或持久化存储。
  • networks(可选):定义网络,让服务之间通信。

模板示例

services:
  web: # 定义一个名为 web 的服务
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    networks:
      - mynet

  db: # 定义一个名为 db 的服务
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - mynet

volumes:
  db_data: {} # 定义持久化存储卷

networks:
  mynet: {} # 定义一个网络

这个模板展示了最常见的结构:一个前端 nginx 和一个后端 mysql 数据库,共享网络 mynet,数据库还使用了持久化卷 db_data


Docker Compose 常用指令

说明:以下示例均为 docker-compose.yml 部分片段;

1) version(可选,Compose V2 起通常省略)

指定 Compose 文件语法版本。V2 起推荐省略,保留也不影响使用。

services:
  app:
    image: alpine
    command: echo "hello"

2) services

定义服务(容器)。键名就是服务名。

services:
  web:
    image: nginx:alpine

3) image

指定使用的镜像(支持 name:tag)。

services:
  web:
    image: nginx:1.27-alpine

4) build

Dockerfile 构建镜像。可用简写或展开配置。

services:
  api:
    build: ./api # 简写:context=./api,Dockerfile 默认名

展开写法(更灵活:自定义 Dockerfile、构建参数等):

services:
  api:
    build:
      context: ./api
      dockerfile: Dockerfile.dev
      target: runtime
      args:
        APP_ENV: production

5) command

覆盖镜像中的 CMD(或作为 entrypoint 的参数)。支持字符串或数组。

services:
  job:
    image: python:3.12-slim
    command: ["python", "main.py", "--once"]

6) entrypoint

覆盖镜像中的 ENTRYPOINT。常用于把容器入口固定为脚本。

services:
  worker:
    image: node:20-alpine
    entrypoint: ["node", "worker.js"]
    command: ["--concurrency=4"] # 作为 entrypoint 的参数

小贴士:优先级为 entrypoint > CMD。两者都写时,command 会作为 entrypoint 的参数。


7) ports

将容器端口映射到宿主机。格式:HOST:CONTAINER

services:
  web:
    image: nginx
    ports:
      - "8080:80" # 宿主机 8080 -> 容器 80

8) expose

仅在 Compose 网络内暴露端口,不映射到宿主机(供同网络下其他服务访问)。

services:
  web:
    image: nginx
    expose:
      - "80" # 仅服务间可见,不对宿主机开放

对比:ports=对外映射;expose=仅对内可见。


9) environment

设置环境变量(键值或从变量继承)。

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: appdb

10) env_file

从文件批量加载环境变量(常配合 .env)。

services:
  api:
    image: my/api:latest
    env_file:
      - .env
      - ./config/api.env

文件内容示例:

PORT=3000
LOG_LEVEL=info

11) volumes

挂载数据卷/目录(持久化或共享数据)。

services:
  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata: {}

12) networks

指定服务加入的网络(隔离与互通)。

services:
  web:
    image: nginx
    networks: [appnet]
  api:
    image: my/api
    networks: [appnet]

networks:
  appnet: {}

13) healthcheck

为服务定义健康检查,供 depends_onservice_healthy 条件使用。

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -proot || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 20s

关键字段:

  • test:检查命令(数组或字符串)。返回 0 视为健康。
  • interval:检查间隔。
  • timeout:单次检查超时。
  • retries:连续失败次数达到后视为不健康。
  • start_period:启动宽限期(在此期间失败不计入 retries)。

14) depends_on(支持健康状态条件)

声明启动/依赖顺序。结合 healthcheck 可等待依赖服务变为健康后再启动。

services:
  web:
    image: nginx:alpine
    depends_on:
      db:
        condition: service_healthy # 等 db 健康后再启动 web

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -proot || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 20s

condition 可选值:

  • service_started:依赖服务启动即满足(默认行为)。
  • service_healthy:依赖服务健康才满足(需配置 healthcheck)。

Docker Compose 命令

Docker Compose 提供了丰富的命令用于管理多容器应用。整体上,这些命令与前面学习的 Docker 容器、镜像操作类似,因此只需掌握常用的即可。

常用命令一览表

命令 功能说明
docker compose up 根据 docker-compose.yml 启动服务(若无镜像则自动构建/拉取)。
docker compose down 停止并删除由 up 创建的容器、网络、卷。
docker compose start 启动已经存在的服务容器(不会新建)。
docker compose stop 停止服务容器但不删除。
docker compose restart 重启服务容器。
docker compose ps 查看 Compose 管理的容器列表及状态。
docker compose logs 查看服务容器的日志。
docker compose run 运行一次性容器(类似 docker run)。
docker compose exec 在正在运行的服务容器中执行命令。
docker compose build 构建或重新构建服务镜像。
docker compose pull 拉取服务镜像。
docker compose config 验证并输出最终的 Compose 配置。
docker compose top 查看服务容器的进程信息。
docker compose events 查看容器事件流。

重点命令详解

1. docker compose up

  • 功能:根据 docker-compose.yml 文件启动服务。

  • 特点:

    • 如果镜像不存在,会自动构建或拉取。
    • 默认在前台运行(可加 -d 参数后台运行)。

示例:

docker compose up -d

后台启动所有服务。


2. docker compose down

  • 功能:停止并删除由 up 创建的容器、网络、卷(默认卷会被删除,挂载的命名卷不会删)。

  • 常用参数:

    • -v:删除匿名卷。
    • --rmi all:删除所有镜像。

示例:

docker compose down -v

停止服务并删除匿名卷。


3. docker compose run

  • 功能:运行一次性容器,适合执行单独任务,不影响已有服务。

  • up 区别:

    • up 是启动整个应用。
    • run 是基于某个服务镜像临时起一个容器。

示例:

docker compose run web echo "hello"

web 服务容器里执行 echo "hello",执行完成后容器会退出。


Docker Compose 实验:图书管理系统容器化编排

本实验将一个基于 Spring Boot 的图书管理系统,通过 Docker Compose 进行多容器编排,实现前端 Nginx、后端 Spring Boot 服务以及 MySQL 数据库的协同运行。

1. 系统结构

实验系统由三个主要服务组成:

服务名称 镜像 端口 功能说明
web nginx:stable-alpine3.21-perl 8110 反向代理前端请求,转发到后端 Spring Boot
backservice openjdk:24-jdk 8080 Spring Boot 后端服务
mysql mysql:8.0.41 3306 数据存储,图书信息及用户信息

各服务通过自定义网络 mylibnet 互相通信。


2. Spring Boot 配置

application.properties 中设置数据库连接与 MyBatis 配置:

spring.application.name=demo

spring.datasource.url=jdbc:mysql://mysql:3306/lib_manage?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=ljx@docker
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis 配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.demo.model
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

注意:allowPublicKeyRetrieval=true 用于解决 MySQL 8.0 默认 caching_sha2_password 的认证问题。


3. Docker Compose 文件

创建 lib_services.yml 文件:

version: "3.9"
services:
  web:
    image: nginx:stable-alpine3.21-perl
    ports:
      - "8110:80"
    networks:
      - mylibnet
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      backservice:
        condition: service_started

  backservice:
    image: openjdk:24-jdk
    depends_on:
      - mysql
    command: java -jar /app/demo-0.0.1-SNAPSHOT.jar
    volumes:
      - ./app/:/app/
    networks:
      - mylibnet

  mysql:
    image: mysql:8.0.41
    environment:
      MYSQL_ROOT_PASSWORD: "ljx@docker"
    networks:
      - mylibnet
    volumes:
      - ./mysql/varlib/:/var/lib/mysql
    healthcheck:
      test:
        [
          "CMD",
          "mysql",
          "--user=root",
          "--password=ljx@docker",
          "-e",
          "SELECT 1;",
        ]
      interval: 10s
      timeout: 5s
      retries: 10

networks:
  mylibnet:
    driver: bridge

4. Nginx 配置

nginx/conf.d/default.conf 中,将请求转发到后端 Spring Boot 服务:

server {
    listen 80;
    access_log off;

    location / {
        proxy_pass http://backservice:8080/;
    }
}

5. 启动容器

lib_services.yml 所在目录执行:

docker compose up -d
  • -d:后台运行容器。
  • 查看日志:
docker compose logs -f backservice
  • 停止并移除容器:
docker compose down

6. 数据库初始化

如果有初始 SQL 文件,可将 .sql 文件放在 mysql 目录下,然后在容器启动后导入:

docker exec -i lib-mysql-1 mysql -uroot -pljx@docker lib_manage < init.sql

7. 实验效果

  • 打开浏览器访问 http://[server_ip]:8110/
    可以看到系统主页,通过 Nginx 访问 Spring Boot 服务。
  • 数据库通过 MySQL 容器提供服务,并持久化存储在本地 ./mysql/varlib/

通过 Docker Compose,本实验实现了图书管理系统的前后端分离 + 数据库独立部署,容器间通过自定义网络通信,整个系统可以快速启动、停止和迁移。