Régis B.
Régis B.

Reputation: 10608

Extend service in docker-compose 3

I created a service for docker-compose 3 that uses many environment variables:

version: "3"

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

Now I want to add a service that uses the same environment variable values, except for VAL1, and that has a different command:

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

Is there any way to avoid the duplication of environment variables in the docker-compose.yml file? In docker-compose 2, it was possible to use the extends keyword but this is no longer the case in docker-compose 3.

EDIT: In October 2017, extension fields were added to the docker-compose 3.4 syntax: https://docs.docker.com/compose/compose-file/#extension-fields This is the right way to go:

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"

Upvotes: 41

Views: 31316

Answers (3)

Andrio Skur
Andrio Skur

Reputation: 788

This is very easy with 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"

See the doc regarding extension-fields

Upvotes: 40

Richard Kiefer
Richard Kiefer

Reputation: 1954

Watch out when using the YAML merge type as suggested by the OP and the extension fields documentation.

The merge type works on dictionaries/maps only, but not on arrays/lists. Fortunately, the environment section can be a dictionary or an array. So the OP's example with the environment section works.

However, the volumes section must be an array, and as such the merging will not work there. The need for an array is not mentioned in the docs, but a quick local test reveals ...volumes contains an invalid type, it should be an array with docker version 18.09.2

In conclusion, anchors, aliases and merge types can help you in many cases, but they do work differently than the merging of multiple compose files via docker-compose -f file1 file2, and different than the extends directive in compose 2. There, merging of lists works as expected.

Upvotes: 5

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38962

You can extract common environment variables to a env file.

Thereafter you can use the env_file configuration option in your compose file.

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

You can still pass/overwrite environment variables other than those specified in common.env using the environment configuration option.

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

Reference

Upvotes: 9

Related Questions