合并撰写文件

Docker Compose 允许您将一组 Compose 文件合并并覆盖在一起,以创建复合 Compose 文件。

默认情况下,Compose 读取两个文件:一个文件compose.yml和一个可选 compose.override.yml文件。按照惯例,其中compose.yml 包含您的基本配置。覆盖文件可以包含现有服务或全新服务的配置覆盖。

如果在两个文件中都定义了服务,Compose 将使用下述规则和 Compose 规范中的规则合并配置。

如何合并多个 Compose 文件

要使用多个覆盖文件或具有不同名称的覆盖文件,您可以使用预定义的 COMPOSE_FILE环境变量,或使用该-f选项指定文件列表。

Compose 按照在命令行上指定的顺序合并文件。后续文件可能会合并、覆盖或添加到其前任文件中。

例如:

$ docker compose -f compose.yml -f compose.admin.yml run backup_db

compose.yml文件可能指定一项webapp服务。

webapp:
  image: examples/web
  ports:
    - "8000:8000"
  volumes:
    - "/data"

还可以compose.admin.yml指定相同的服务:

webapp:
  environment:
    - DEBUG=1

任何匹配的字段都会覆盖先前的文件。新值,添加到webapp服务配置中:

webapp:
  image: examples/web
  ports:
    - "8000:8000"
  volumes:
    - "/data"
  environment:
    - DEBUG=1
    - ANOTHER_VARIABLE=value

重要的

使用多个 Compose 文件时,必须确保文件中的所有路径都相对于基本 Compose 文件(使用 指定的第一个 Compose 文件-f)。这是必需的,因为覆盖文件不必是有效的 Compose 文件。覆盖文件可以包含配置的小片段。跟踪服务的哪个片段相对于哪个路径是困难且令人困惑的,因此为了使路径更易于理解,所有路径都必须相对于基本文件进行定义。

附加信息

  • 使用-f是可选的。如果未提供,Compose 会在工作目录及其父目录中搜索 acompose.yml和 acompose.override.yml文件。您必须至少提供该compose.yml文件。如果两个文件存在于同一目录级别,Compose 会将它们组合成一个配置。

  • 当您使用多个 Compose 文件时,文件中的所有路径都相对于使用-f.您可以使用该--project-directory选项来覆盖此基本路径。

  • 您可以使用-f-(破折号)作为文件名来读取配置stdin。例如:

    $ docker compose -f - <<EOF
      webapp:
        image: examples/web
        ports:
         - "8000:8000"
        volumes:
         - "/data"
        environment:
         - DEBUG=1
      EOF
    

    使用时stdin,配置中的所有路径都相对于当前工作目录。

  • 您可以使用该标志来指定不在当前目录中的 Compose 文件的路径,无论是从命令行还是通过在 shell 或环境文件中-f设置 COMPOSE_FILE 环境变量。

    例如,如果您正在运行 Compose Rails 示例,并且compose.yml在名为 的目录中有一个文件sandbox/rails。您可以使用docker compose pull这样的命令 ,db通过使用以下标志从任何地方获取该服务的 postgres 映像-fdocker compose -f ~/sandbox/rails/compose.yml pull db

    这是完整的示例:

    $ docker compose -f ~/sandbox/rails/compose.yml pull db
    Pulling db (postgres:latest)...
    latest: Pulling from library/postgres
    ef0380f84d05: Pull complete
    50cf91dc1db8: Pull complete
    d3add4cd115c: Pull complete
    467830d8a616: Pull complete
    089b9db7dc57: Pull complete
    6fba0a36935c: Pull complete
    81ef0e73c953: Pull complete
    338a6c4894dc: Pull complete
    15853f32f67c: Pull complete
    044c83d92898: Pull complete
    17301519f133: Pull complete
    dcca70822752: Pull complete
    cecf11b8ccf3: Pull complete
    Digest: sha256:1364924c753d5ff7e2260cd34dc4ba05ebd40ee8193391220be0f9901d4e1651
    Status: Downloaded newer image for postgres:latest
    

合并规则

Compose 将配置从原始服务复制到本地服务。如果在原始服务和本地服务中都定义了配置选项,则本地值将替换或扩展原始值。

image对于诸如、command或 之类的单值选项mem_limit,新值将替换旧值。

原服务:

services:
  myservice:
    # ...
    command: python app.py

本地服务:

services:
  myservice:
    # ...
    command: python otherapp.py

结果:

services:
  myservice:
    # ...
    command: python otherapp.py

对于多值选项portsexposeexternal_linksdnsdns_searchtmpfs,Compose 连接两组值:

原服务:

services:
  myservice:
    # ...
    expose:
      - "3000"

本地服务:

services:
  myservice:
    # ...
    expose:
      - "4000"
      - "5000"

结果:

services:
  myservice:
    # ...
    expose:
      - "3000"
      - "4000"
      - "5000"

environment在、labelsvolumes和的情况下devices,Compose 将条目与优先的本地定义值“合并”在一起。对于 environmentlabels,环境变量或标签名称决定使用哪个值:

原服务:

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=original

本地服务:

services:
  myservice:
    # ...
    environment:
      - BAR=local
      - BAZ=local

结果:

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=local
      - BAZ=local

volumes和的条目devices使用容器中的安装路径进行合并:

原服务:

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./original:/bar

本地服务:

services:
  myservice:
    # ...
    volumes:
      - ./local:/bar
      - ./local:/baz

结果:

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./local:/bar
      - ./local:/baz

有关更多合并规则,请参阅 Compose 规范中的合并和覆盖。

例子

多个文件的常见用例是将开发 Compose 应用程序更改为类似生产的环境(可能是生产、登台或 CI)。为了支持这些差异,您可以将 Compose 配置拆分为几个不同的文件:

从定义服务规范配置的基本文件开始。

compose.yml

services:
  web:
    image: example/my_web_app:latest
    depends_on:
      - db
      - cache

  db:
    image: postgres:latest

  cache:
    image: redis:latest

在此示例中,开发配置向主机公开一些端口,将我们的代码安装为卷,并构建 Web 映像。

compose.override.yml

services:
  web:
    build: .
    volumes:
      - '.:/code'
    ports:
      - 8883:80
    environment:
      DEBUG: 'true'

  db:
    command: '-d'
    ports:
     - 5432:5432

  cache:
    ports:
      - 6379:6379

当您运行时,docker compose up它会自动读取覆盖。

要在生产环境中使用此 Compose 应用程序,需要创建另一个覆盖文件,该文件可能存储在不同的 git 存储库中或由不同的团队管理。

compose.prod.yml

services:
  web:
    ports:
      - 80:80
    environment:
      PRODUCTION: 'true'

  cache:
    environment:
      TTL: '500'

要使用此生产 Compose 文件进行部署,您可以运行

$ docker compose -f compose.yml -f compose.prod.yml up -d

这将使用 中的配置部署所有三个服务 compose.yml,但compose.prod.yml不使用 中的开发配置compose.override.yml

有关更多信息,请参阅 在生产中使用 Compose

局限性

Docker Compose 支持要包含在应用程序模型中的许多资源的相对路径:服务映像的构建上下文、定义环境变量的文件位置、绑定安装卷中使用的本地目录的路径。有了这样的限制,单一存储库中的代码组织可能会变得困难,因为自然的选择是每个团队或组件都有专用文件夹,但随后 Compose 文件相对路径变得无关紧要。

参考信息