dockervariablesduplicatesdocker-composecode-duplication

Is there way in docker compose to create the cross service constant?


I have compose file like this:

service1:
   //some stuff
   environment:
  - "PROP=some_common_value"
service2:
  //some stuff
  environment:
  - "PROP=some_common_value"
service2:
  //some stuff
  environment:
  - "PROP=some_common_value"

I want to set properties with the same values.

As you can I now I copy past that value. It looks awful.
Is there way in docker compose to create the cross service constant?


Solution

  • There are a couple options. If you deploy with docker-compose and not docker stack deploy, then you can use a .env file to set variables. Or with either docker-compose or swarm mode, you can set an environment variable in your shell (often a shell script used to deploy the app). Inside of the yaml, you would use the environment variable like:

    service1:
      environment:
      - PROP
    service2:
      environment:
      - PROP
    service2:
      environment:
      - PROP
    

    or explicitly use the variable like:

    service1:
      environment:
      - PROP=${PROP}
    service2:
      environment:
      - PROP=${PROP}
    service3:
      environment:
      - PROP=${PROP}
    

    If you have a .env file and want to do a docker stack deploy, you can script the processing of that with either of:

    # option 1, leaves vars set in shell
    set -a && . .env && set +a && docker stack deploy -c compose.yml stack_name
    
    # option 2, only sets vars for single command
    env $(cat .env | xargs) docker stack deploy -c compose.yml stack_name
    

    In each of the above, the .env is just the variables you could otherwise set in your shell:

    PROP=some_common_value
    

    The next option is to use Yaml syntax of anchors and aliases. This copies from one section of a Yaml file to another (to support merging in service3, I switched to key/value instead of the array syntax):

    service1:
      environment: &common_env
        PROP: "some_common_value"
    service2:
      environment: *common_env
    service3:
      environment:
        <<: *common_env
        PROP3: "unique value"
    

    To allow each service to have unique values, Docker added extension fields in recent versions of the compose syntax. This lets you define an anchor separate from any of the service definitions and merge it into each service, each with their own unique values, e.g.:

    version: '3.4'
    x-common-env: &common_env
      PROP: "some_common_value"
    services:
      service1:
        environment:
          <<: *common_env
          PROP1: "unique value 1"
      service2:
        environment:
          <<: *common_env
          PROP2: "unique value 2"
      service3:
        environment:
          <<: *common_env
          PROP3: "unique value 3"