合并 Compose 文件

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

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

如果在这两个文件中都定义了服务,则 Compose 会使用 下面和 Compose 规范中描述的规则。

如何合并多个 Compose 文件

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

Compose 将文件合并到 它们在命令行上指定的顺序。后续文件可能会合并、覆盖或 添加到他们的前辈。

例如:

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

compose.yaml文件可能会指定webapp服务。

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

compose.admin.yaml也可以指定相同的服务:

webapp:
  environment:
    - DEBUG=1

任何匹配项 fields 将覆盖上一个文件。新值,添加到webapp服务 配置:

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

合并规则

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

    提示

    您可以使用docker compose config查看合并的配置并避免与路径相关的问题。

  • Compose 会将配置从原始服务复制到本地服务。 如果在原始服务和本地 service,则 local 值将替换或扩展原始值。

    • 对于单值选项(如image,commandmem_limit,则新值将替换旧值。

      原厂服务:

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

      本地服务:

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

      结果:

      services:
        myservice:
          # ...
          command: python otherapp.py
    • 对于多值选项ports,expose,external_links,dns,dns_searchtmpfs中,Compose 会连接这两组值:

      原厂服务:

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

      本地服务:

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

      结果:

      services:
        myservice:
          # ...
          expose:
            - "3000"
            - "4000"
            - "5000"
    • environment,labels,volumesdevices中,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
    • 条目volumesdevices使用容器中的挂载路径进行合并:

      原厂服务:

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

      本地服务:

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

      结果:

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

有关更多合并规则,请参阅 Compose 规范中的 Merge and override

其他信息:

  • -f是可选的。如果未提供,Compose 会在工作目录及其父目录中搜索compose.yaml以及compose.override.yaml文件。您必须至少提供compose.yaml文件。如果这两个文件都位于同一目录级别,则 Compose 会将它们合并到一个配置中。

  • 您可以使用-f其中 (dash) 作为读取配置的文件名-stdin.例如:

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

    什么时候stdin,则配置中的所有 paths 都是相对于当前工作目录的。

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

    例如,如果您正在运行 Compose Rails 示例,并且有一个compose.yaml文件中名为sandbox/rails.您可以使用类似 docker compose pull 的命令来获取dbservice 从任何地方使用-f标志,如下所示:docker compose -f ~/sandbox/rails/compose.yaml pull db

    以下是完整的示例:

    $ docker compose -f ~/sandbox/rails/compose.yaml 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 应用 对于类似生产的环境(可能是生产、暂存或 CI)。 为了支持这些差异,您可以将 Compose 配置拆分为 几个不同的文件:

从定义 服务业。

compose.yaml

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

  db:
    image: postgres:latest

  cache:
    image: redis:latest

在此示例中,开发配置将一些端口暴露给 host,将我们的代码挂载为卷,并构建 Web 镜像。

compose.override.yaml

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.yaml

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

  cache:
    environment:
      TTL: '500'

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

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

这将使用compose.yamlcompose.prod.yaml但不是 dev 配置compose.override.yaml.

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

局限性

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

参考资料