【问题标题】:Extend service in docker-compose 3在 docker-compose 3 中扩展服务
【发布时间】:2017-12-29 23:38:04
【问题描述】:

我为 docker-compose 3 创建了一个使用许多环境变量的服务:

version: "3"

services:
  myservice:
    build:
      context: ./myservice
    command: ./something
    environment:
      VAR1: "val1"
      VAR2: "val2"
      VAR3: "val3"

现在我想添加一个使用相同环境变量值的服务,VAL1 除外,并且具有不同的命令:

myotherservice:
    build:
      context: ./myservice
    command: ./somethingelse
    environment:
      VAR1: "val1-bis"
      VAR2: "val2"
      VAR3: "val3"

有什么办法可以避免docker-compose.yml文件中的环境变量重复?在 docker-compose 2 中,可以使用 extends 关键字,但在 docker-compose 3 中不再是这种情况。

编辑:2017 年 10 月,扩展字段被添加到 docker-compose 3.4 语法中:https://docs.docker.com/compose/compose-file/#extension-fields 这是正确的方法:

version: "3"
x-env:
  &default-env
  VAR1: "val1"
  VAR2: "val2"
  VAR3: "val3"
services:
  myservice:
    build:
      context: ./myservice
    command: ./something
    environment: *default-env
myotherservice:
    build:
      context: ./myservice
    command: ./somethingelse
    environment:
      << : *default-env
      VAR1: "val1-bis"

【问题讨论】:

  • 注意:对此有一个开放的issue - 但没有人知道他们是否会对此采取任何行动;(
  • 他们严重删除了最有用的功能之一......这太疯狂了

标签: docker docker-compose


【解决方案1】:

您可以将常用环境变量提取到 env 文件中。

此后您可以在撰写文件中使用env_file 配置选项。

-> cat common.env
      VAR2=val2
      VAR3=val3

您仍然可以使用environment 配置选项传递/覆盖除common.env 中指定的环境变量以外的环境变量。

myotherservice:
  build:
    context: ./myservice
  command: ./somethingelse
  env_file: ./common.env
  environment:
    VAR1: "val1-bis"

参考

【讨论】:

  • 在这种情况下,如果 env 文件的名称发生更改,则必须在所有服务中更改。通过在一个地方进行更改可以避免“扩展”。好吧,您可能会问文件名更改了多少次。
  • @ChrisOdney 是的,你是对的,只是在 v3 中不推荐使用扩展
  • @OluwafemiSule 是的,我知道,这就是我要指出的讽刺。
  • 仅供参考,我添加了一个基于 docker-compose 3.4 的新解决方案(在我的问题得到解答后发布)
  • 感谢您指出这一点。但是,使用env_file指令指向文件创建环境变量和使用.env文件实际上是两个不同的概念。
【解决方案2】:

使用 YAML 很容易:

version: "3"

services:
  myservice: &myservice
    build:
      context: ./myservice
    command: ./something
    environment: &myservice_environment
      VAR1: "val1"
      VAR2: "val2"
      VAR3: "val3"

myotherservice:
    <<: *myservice
    environment:
      <<: *myservice_environment
      VAR1: "val1-bis"

the doc regarding extension-fields

【讨论】:

  • 你不知道docker-compose的yaml解析器是否支持这种语法?太棒了!
  • @RégisB。是的 v3.7 >= docs.docker.com/compose/compose-file/#extension-fields 。我在我的项目中使用它
  • 这太棒了,非常感谢。我添加了您的答案的链接(等待批准),因为这是它应该去的地方 imho :) 此外,这应该是公认的答案,因为问题标题要求一个更一般的概念,而不仅仅是环境变量。
  • 这个答案具有误导性。使用(即&amp; and &lt;&lt;)重用 YAML 配置不是 compose-file 的功能。这只是 YAML 的合并类型功能。阅读此内容以供参考:yaml.org/type/merge.html。而正确的解释应该是“可以将此答案中的语法与撰写文件的扩展字段功能一起使用”。
  • @EricDarchis 你能提供一个包含这些错误的代码吗?
【解决方案3】:

在使用 OP 和 extension fields 文档建议的 YAML 合并类型时要小心。

合并类型适用于dictionaries/maps only,但不适用于数组/列表。幸运的是,环境部分可以是dictionary or an array。因此,OP 的环境部分示例有效。

但是,volumes 部分必须是一个数组,因此merging will not work there。文档中没有提到对数组的需求,但快速的本地测试显示 ...volumes contains an invalid type, it should be an array 与 docker 版本 18.09.2

总之,锚点、别名和合并类型在许多情况下可以帮助您,但它们的工作方式与通过docker-compose -f file1 file2 合并多个撰写文件不同,也不同于extends directive in compose 2。在那里,列表的合并按预期工作。

【讨论】: