Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"
like image 753
Régis B. Avatar asked Jul 24 '17 11:07

Régis B.


People also ask

What is the extension of Docker compose?

The Compose file is a YAML file defining services, networks and volumes. The default path for a Compose file is ./docker-compose.yml . Tip: You can use either a .yml or .yaml extension for this file. They both work.

What is Depends_on in Docker compose?

depends_on is a Docker Compose keyword to set the order in which services must start and stop. For example, suppose we want our web application, which we'll build as a web-app image, to start after our Postgres container.


3 Answers

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

like image 191
Andrio Skur Avatar answered Oct 03 '22 18:10

Andrio Skur


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

  • https://docs.docker.com/compose/environment-variables/#the-env-file
like image 32
Oluwafemi Sule Avatar answered Oct 03 '22 18:10

Oluwafemi Sule


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.

like image 30
Richard Kiefer Avatar answered Oct 03 '22 18:10

Richard Kiefer