1. 概述

在使用 Docker 的过程中,如果同时管理多个容器,很快就会变得繁琐复杂。

Docker Compose 是一个帮助我们解决这个问题的工具,它能让我们轻松地一次性管理多个容器

在本教程中,我们将介绍 Docker Compose 的核心功能及其强大的机制。


2. YAML 配置详解

Docker Compose 的工作原理是基于一个名为 docker-compose.yml 的配置文件。这个 YAML 格式的文件集中定义了多个服务、卷(volumes)和网络(networks)等规则。

YAML 是一种既易于人阅读,又便于机器解析的格式,非常适合用于快速描述整个项目的结构。

几乎每一个配置项都对应于一个 Docker 命令。这意味着我们只需要运行:

docker-compose up

就能自动完成多个容器的创建、网络配置、卷挂载等复杂操作,省去了手动编写脚本的麻烦。

基本结构如下:

version: "3.7"
services:
  ...
volumes:
  ...
networks:
  ...

接下来我们分别看看这些核心元素的作用。

2.1. 服务(Services)

服务(Service)是 Docker Compose 中的核心概念,它定义了容器的运行时配置。

比如一个典型的 Web 应用可能包括前端、后端和数据库三个组件,我们可以将它们分别定义为三个服务:

services:
  frontend:
    image: my-vue-app
  backend:
    image: my-springboot-app
  db:
    image: postgres

每个服务可以配置镜像、端口映射、卷挂载、依赖关系等。

2.2. 卷(Volumes)与网络(Networks)

卷(Volume)用于在主机与容器之间共享数据,也可以用于多个容器之间共享数据。可以理解为容器可见的“共享目录”。

网络(Network)定义了容器之间的通信规则。公共网络中的容器可以互相访问,私有网络则起到了隔离作用。

我们将在下文详细讨论这些配置。


3. 服务配置详解

下面我们将深入探讨服务的常用配置项。

3.1. 使用现有镜像

如果你的服务所需的镜像已经在 Docker Hub 或其他仓库中存在,可以使用 image 指定镜像名称和标签:

services:
  my-service:
    image: ubuntu:latest

3.2. 构建自定义镜像

如果需要从源码构建镜像,使用 build 指定 Dockerfile 的路径:

services:
  my-custom-app:
    build: /path/to/dockerfile/

也可以直接使用 Git 仓库地址:

services:
  my-custom-app:
    build: https://github.com/my-company/my-project.git

如果同时指定 image,则构建后的镜像会使用这个名称:

services:
  my-custom-app:
    build: https://github.com/my-company/my-project.git
    image: my-project-image

3.3. 网络配置

Docker 容器之间的通信依赖于网络。服务可以通过服务名和端口互相访问,前提是该端口已通过 expose 暴露:

services:
  network-example-service:
    image: karthequian/helloworld:latest
    expose:
      - "80"

如果希望从宿主机访问容器服务,则需要使用 ports 显式映射端口:

services:
  network-example-service:
    image: karthequian/helloworld:latest
    ports:
      - "80:80"

也可以映射不同的端口号:

services:
  my-custom-app:
    image: myapp:latest
    ports:
      - "8080:3000"

还可以定义多个网络,实现容器隔离:

services:
  network-example-service:
    image: karthequian/helloworld:latest
    networks:
      - my-shared-network
networks:
  my-shared-network: {}

3.4. 卷配置

Docker 支持三种类型的卷:匿名卷、命名卷和主机卷。

  • 匿名卷:由 Docker 自动生成,生命周期与容器绑定。
  • 命名卷:推荐使用,由 Docker 管理,生命周期独立于容器。
  • 主机卷:将宿主机目录挂载到容器中。

示例:

services:
  volumes-example-service:
    image: alpine:latest
    volumes:
      - my-named-global-volume:/my-volumes/named-global-volume
      - /tmp:/my-volumes/host-volume
      - /home:/my-volumes/readonly-host-volume:ro
volumes:
  my-named-global-volume:

其中:

  • my-named-global-volume 是命名卷,多个服务可以共享。
  • /tmp 是主机卷,容器可读写。
  • /home 以只读方式挂载(通过 :ro)。

3.5. 服务依赖关系

通过 depends_on 可以定义服务之间的启动顺序:

services:
  kafka:
    image: wurstmeister/kafka:2.11-0.11.0.3
    depends_on:
      - zookeeper
  zookeeper:
    image: wurstmeister/zookeeper

⚠️ 注意:depends_on 仅保证依赖服务已启动,不保证其完全就绪。如需精确控制启动顺序,需结合健康检查或脚本。


4. 环境变量管理

Docker Compose 支持环境变量配置,可以在 environment 中定义:

services:
  database:
    image: "postgres:${POSTGRES_VERSION}"
    environment:
      DB: mydb
      USER: "${USER}"

变量值可以通过以下方式提供:

  • .env 文件:
POSTGRES_VERSION=alpine
USER=foo
  • 命令行导出:
export POSTGRES_VERSION=alpine
export USER=foo
docker-compose up
  • 一行命令指定:
POSTGRES_VERSION=alpine USER=foo docker-compose up

还可以为变量设置默认值:

environment:
  DB: mydb
  USER: "${USER:-admin}"

如果 USER 未设置或为空,则使用 admin。如果希望允许空值传入,使用:

USER: "${USER-admin}"

5. 扩展与副本

旧版本中使用 docker-compose scale 扩展服务实例,新版本已改为使用 --scale 参数,并结合 Docker Swarm 实现。

例如:

services:
  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 6
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M

⚠️ 注意:deploy 配置仅在使用 Docker Swarm 模式时生效。


6. 实战案例:Spring Cloud Data Flow

理论讲得再多,不如实战来得直观。Spring Cloud Data Flow 是一个典型使用 Docker Compose 的项目。

你可以下载其官方 YAML 文件并运行:

DATAFLOW_VERSION=2.1.0.RELEASE SKIPPER_VERSION=2.0.2.RELEASE docker-compose up

Docker Compose 会自动下载、配置并启动所有组件,并将日志统一输出到当前终端,每个容器日志还会以不同颜色区分,提升可读性:

用户界面截图

常见错误:

lookup registry-1.docker.io: no such host

✅ 解决方案之一是设置 DNS 为 8.8.8.8


7. 生命周期管理

Docker Compose 提供了完整的生命周期管理命令。

7.1. 启动服务

启动所有服务(首次运行):

docker-compose up

以后可以直接启动:

docker-compose start

指定非默认配置文件:

docker-compose -f custom-compose-file.yml start

后台运行:

docker-compose up -d

7.2. 停止服务

停止服务(保留数据):

docker-compose stop

重置环境(删除容器、网络,但保留外部卷):

docker-compose down

8. 总结

Docker Compose 是管理多容器应用的利器。通过一个 YAML 文件,我们可以定义服务、网络、卷、环境变量、依赖关系等复杂配置,极大简化了 Docker 的使用成本。

如需查看完整 docker-compose.yml 示例文件,可访问我们的 GitHub 仓库:

docker file

源码地址:GitHub 示例仓库


原始标题:Introduction to Docker Compose