在docker-compose.yml中重复使用环境变量

154

是否可以重复使用在多个容器之间共享的环境变量?

这个想法是为了避免重复,就像这个例子所示:

version: '2'

services:

  db:
    image: example/db
    ports:
      - "8443:8443" 
    container_name: db
    hostname: db
    environment:
      - USER_NAME = admin 
      - USER_PASSWORD = admin 

svc:
  image: example/svc
  depends_on:
    - db
  ports:
    - "9443:9443"
  container_name: svc
  hostname: svc
  environment:
    - DB_URL = https://db:8443
    - DB_USER_NAME = admin
    - DB_USER_PASSWORD = admin 
3个回答

248

extends选项可能很好用,但在3.xcompose文件中不受支持。其他可选方式包括:

  1. 扩展字段(compose文件3.4+)

    如果可以使用3.4+ compose文件,则扩展字段可能是最佳选择:

    docker-compose.yml

 version: '3.4'

 x-common-variables: &common-variables
   VARIABLE: some_value
   ANOTHER_VARIABLE: another_value

 services:
   some_service:
     image: someimage
     environment: *common-variables

   another_service:
     image: anotherimage
     environment:
       <<: *common-variables
       NON_COMMON_VARIABLE: 'non_common_value'
  • env_file 指令

    docker-compose.yml

  •  version: '3.2'
    
     services:
       some_service:
         image: someimage
         env_file:
           - 'variables.env'
    
       another_service:
         image: anotherimage
         env_file:
           - 'variables.env'
    

    variables.env

     VARIABLE=some_value
     ANOTHER_VARIABLE=another_value
    
  • .env 文件位于项目根目录 (或实际compose环境中的变量)

    来自.env文件的变量可以在服务配置中引用:

    docker-compose.yml

  •  version: '3.2'
    
     services:
       some_service:
         image: someimage
         environment:
           - VARIABLE
    
       another_service:
         image: anotherimage
         environment:
           - VARIABLE
           - ANOTHER_VARIABLE
    

    .env

    :一个文件,用于在应用程序中存储配置变量。这些变量通常是敏感的,如数据库凭据或API密钥,应该通过环境变量来设置,以免泄露到代码库或生产环境中。
     VARIABLE=some_value
     ANOTHER_VARIABLE=another_value
    

    6
    对于不太熟悉YAML的人来说:请参考YAML中的“合并键语言”以了解符号的原因==> environment: <<: common-variables。基本上,&foo表示“foo将被重复使用”,foo表示重复使用一个变量,而<<:将随后的变量映射插入到当前键中。我想编辑但是居然出现了编辑队列已满的提示。 - logicOnAbstractions
    @logicOnAbstractions 我提供的扩展字段文档链接就足够了,其中解释了YAML功能。 - Wolphin
    1
    能否在 docker-compose.yml 中重复使用扩展字段进行替换? - Andrius
    1
    扩展字段非常适用于重复使用映射,但不幸的是合并键不支持数组。有人知道如何解决使用扩展字段处理数组的问题吗? - colelemonz
    1
    @colelemonz,我们最好能够重复使用特定键的值:https://dev59.com/Om445IYBdhLWcg3wRoPH#27022292 - Wolphin
    1
    @Wolphin是正确的!这很误导,会浪费比我想象中更多的时间!!! - the_real_one

    47
    您可以使用extends指令(适用于compose 1.x2.x)让多个容器继承底层服务描述中的environment配置。例如,在名为base.yml的文件中添加以下内容:
    version: '2'
    
    services:
      base:
        environment:
          DB_URL: https://db:8443
          DB_USER_NAME: admin
          DB_USER_PASSWORD: admin 
    

    然后在你的docker-compose.yml文件中:

    version: '2'
    
    services:
      container1:
        image: alpine
        command: sh -c "env; sleep 900"
        extends:
          file: base.yml
          service: base
    
      container2:
        image: alpine
        command: sh -c "env; sleep 900"
        extends:
          file: base.yml
          service: base
        environment:
          ANOTHERVAR: this is a test
    

    然后在container1内,你会看到:

    DB_URL=https://db:8443
    DB_USER_NAME=admin
    DB_USER_PASSWORD=admin
    

    container2 中,您将看到:

    DB_URL=https://db:8443
    DB_USER_NAME=admin
    DB_USER_PASSWORD=admin
    ANOTHERVAR=this is a test
    

    当使用docker-compose时,extends不仅可以用于environment指令,还可以用于其他方面,这是避免重复的好方法。


    extends 对于我的使用情况非常有效。它比本地变量更可取,因为它消除了对特定用户的依赖性。我可以通过 extends 指定常见的容器标签。 - Sergei Rodionov
    我可以在一个服务中extends多个服务吗?或者一个服务从多个文件中继承? - Philipp Kyeck
    如果其他人在从子目录调用文件时遇到了FileNotFoundError,可以使用文件的相对路径而不是绝对路径:"./base.yml" - Adverbly

    8
    您可以在docker-compose文件中引用本地环境变量。假设您想要的是将USER_NAME设置为与DB_USER_NAME相同:

    docker-compose.yml

    version: '2'
    
    services:
      db:
        image: example/db
        ports:
          - "8443:8443" 
        container_name: db
        hostname: db
        environment:
          - USER_NAME = ${USERNAME}
          - USER_PASSWORD = ${PASSWORD}
    
    svc:
      image: example/svc
      depends_on:
        - db
      ports:
        - "9443:9443"
      container_name: svc
      hostname: svc
      environment:
        - DB_URL = https://db:8443
        - DB_USER_NAME = ${USERNAME}
        - DB_USER_PASSWORD = ${PASSWORD}
    

    然后,像这样运行docker-compose:

    $ USERNAME="admin" PASSWORD="admin" docker-compose up
    

    如果需要更为固定且易于重复输入的内容:

    可以选择以下方式:

    $ printf '%s\n%s\n' 'export USERNAME="admin"' 'export PASSWORD="admin"' >> ~/.bash_profile
    $ source ~/.bash_profile
    $ docker-compose up
    

    4
    我认为 $ USERNAME="admin" PASSWORD="admin" docker-compose up 不太好。黑客可以使用 $ history 命令获取历史记录并获得密码。 - Changwoo Rhee
    2
    @ChangwooRhee 如果你在本地使用敏感凭据来进行docker-compose,那么你面临的问题并不是技术相关的。 - ThatsNinja
    在非版本化文件中存储本地敏感凭据等是不好的,但像你这样传递它们更糟糕,而且关于其他事情的争论并不能否定这是错误的建议。 - James
    1
    @James 或许我应该更明确地表达:敏感凭证永远不应该存储在本地。事实上,理想情况下,生产数据库的密码不应该被任何人知道。 - ThatsNinja

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接