【问题标题】:Is there any way to use extension fields in docker-compose with docker secrets?有没有办法在 docker-compose 中使用扩展字段和 docker secrets?
【发布时间】:2025-12-24 10:05:15
【问题描述】:

假设我们有一个由 .yml 文件配置的 docker 堆栈,其中包含 3 个服务 - a、b 和 c。此外,这些服务使用了很多秘密。两个用于数据库、Azure 服务,每个服务都有一些独特的。因此,我们的 .yml 文件如下所示:

version: '3.4'

services:
 a:
  image: a-image
  [...]
  secrets:
   -db.pwd
   -db.user
   -azure.secret_key
   -azure.public_key
   -a.secret_key1
   -a.secret_key2
 b:
  image: b-image
  [...]
  secrets:
   -db.pwd
   -db.user
   -b.secret_key1
   -b.secret_key2
 c:
  image: c-image
  [...]
  secrets:
   -db.pwd
   -db.user
   -azure.secret_key
   -azure.public_key
   -c.secret_key1
   -c.secret_key2

secrets:
 db.pwd:
  external: true
 db.user:
  external: true
 azure.secret_key:
  external: true
 azure.public_key:
  external: true
 a.secret_key1:
  external: true
 a.secret_key2:
  external: true
 b.secret_key1:
  external: true
 b.secret_key2:
  external: true
 c.secret_key1:
  external: true
 c.secret_key2:
  external: true

如您所见,每个服务都重复了一些秘密。 docker-compose 文件有“扩展字段”之类的东西 - https://docs.docker.com/compose/compose-file/#extension-fields 有什么办法可以使用这个扩展字段来避免重复秘密? 像这样的:

version: '3.4'
x-common-db-secrets: &db-secrets
 - db.user
 - db.pwd

x-common-azure-secrets: &azure-secrets
 - azure.public_key
 - azure.secret_key

services:
 a:
  image: a-image
  [...]
  secrets:
   <<: *db-secrets
   <<: *azure-secrets
   -a.secret_key1
   -a.secret_key2
 b:
  image: b-image
  [...]
  secrets:
   <<: *db-secrets
   -b.secret_key1
   -b.secret_key2
 c:
  image: c-image
  [...]
  secrets:
   <<: *db-secrets
   <<: *azure-secrets
   -c.secret_key1
   -c.secret_key2

secrets:
 [...]

我正在使用此扩展字段来共享环境变量。但是解析扩展字段所需的结构是map。 “秘密”部分需要列表。有谁知道如何处理它吗?请注意,将来可以添加新的秘密,例如用于旧服务和新服务,因此解决方案必须灵活。我将不胜感激找到答案。正在寻找任何 compose 版本 3.4+ 的答案。

【问题讨论】:

    标签: docker docker-compose yaml devops docker-swarm


    【解决方案1】:

    无法使用 YAML 锚点和别名将列表项组合成一个平面列表。但是,docker-compose 对 Compose 文件有自己的深度合并过程,您可以将其与 YAML 锚点和别名组合以获得您正在寻找的效果。为此,您需要将服务定义拆分为两个文件。这是一个例子

    foo.yml

    此 Compose 文件有一个名为 x-secrets 的扩展名,它声明了名为 onetwo 的机密。它有一个名为secrets 的锚点,它用于为ab 服务填写公共机密。

    version: "3.7"
    
    x-secrets: &secrets
      secrets:
        - one
        - two
    
    services:
      a:
        <<: *secrets
        image: a-image
    
      b:
        <<: *secrets
        image: b-image
    
    secrets:
      one:
        external: true
      two:
        external: true
    

    bar.yml

    接下来,这个 Compose 文件扩展了服务 a 并添加了两个额外的秘密,名为 threefour

    version: "3.7"
    
    services:
      a:
        secrets:
          - three
          - four
    
    secrets:
      three:
        external: true
      four:
        external: true
    

    组合编写文件

    有了这两个文件,告诉 docker-compose 将它们都用于项目配置。这些文件将按顺序合并以形成一个完整的配置。我正在使用config 命令来显示最终配置。

    $ docker-compose -f foo.yml -f bar.yml config
    secrets:
      four:
        external: true
        name: four
      one:
        external: true
        name: one
      three:
        external: true
        name: three
      two:
        external: true
        name: two
    services:
      a:
        image: a-image
        secrets:
        - source: four
        - source: one
        - source: three
        - source: two
      b:
        image: b-image
        secrets:
        - source: one
        - source: two
    version: '3.7'
    

    在这里,您可以看到服务a 现在有四个秘密。来自foo.ymlbar.yml 的机密列表已合并在一起。

    顺便说一句,您可以使用名为 COMPOSE_FILE 的环境变量指定 Compose 文件列表,也可以将其放在名为 .env 的文件中。

    【讨论】:

    • 组合文件 - 似乎不是解决此类问题的正确方法,因为如果新的秘密增加,用于组合的文件数量将会增加。
    • 我实际上建议为各种用例使用多个 Compose 文件。在你的情况下,你不应该需要超过两个。将所有常用配置放在一个 (foo.yml) 中,将所有服务的所有附加功能放在另一个 (bar.yml) 中。不幸的是,仅使用 YAML 锚点和别名对于列表来说是不够的。
    • 不幸的是,这不是我的用例,它是一个例子。因为我有超过 15 种不同的服务,它们具有共同和独特的秘密。在这种情况下,多个文件会使其更加复杂。就我而言,即使像我的第一个示例中描述的那样重复代码听起来也更好。无论如何,谢谢你的回答。
    最近更新 更多