Search code examples
dockerdocker-composeyamlyaml-anchors

How to prevent overwriting the whole environment field while using YAML anchors


I am writing my docker-compose.yml file and to avoid writing redundant lines especially for using different profiles for dev, uat, prod etc, I was using yaml anchors. Here is a sample for one of the adapters I used for uat and for dev.

Adapter:&Adapter
  image:"my-image"
  profiles:
    - uat
  environment:
    - JAVA_OPTS="${JAVA_OPTS} -Dloader.main=com.my.class"
    - SPRING_PROFILES_ACTIVE=uat
  volumes:
    - /local/path/to/logs:/logs
  depends_on:
    - some_image

Adapter-dev:
  <<: *Adapter
  profiles:
    - dev
  environment:
    - SPRING_PROFILES_ACTIVE=dev

.env file contains:

JAVA_OPTS=-Xmx3g -Xms3g

The key part is that the JAVA_OPTS is a must have in order to run properly. The JAVA_OPTS is stored in a .env file, and I append to the JAVA_OPTS variable to specify my main class. I just found out that doing it in the way above, it overwrites the environment entirely and only passes the SPRING_PROFILES_ACTIVE to my docker container's environment variables. What I expected would be that only SPRING_PROFILES_ACTIVE would be overwritten, but the JAVA_OPTS would be preserved. How can I only overwrite the SPRING_PROFILES_ACTIVE in my docker-compose.yml without overwriting the JAVA_OPTS?


Solution

  • The specific solution used was to utilise a common-services.yml file. This allowed me to only run the services with the specified profile without running the default services. What I did was to extract the default service to an additional yml file like so:

    #common-services.yml:
    services:
      adapter:
        image: "my-image"
        profiles: []
        environment:
          - JAVA_OPTS="${JAVA_OPTS} -Dloader.main=com.my.class"
        volumes:
          - /local/path/to/logs:/logs
    

    and the docker compose yaml will look like:

    #docker-compose.yml
    version: '3.9'
    services:
      adapter-uat:
        extends:
          file: common-services.yml
          service: adapter
        profiles:
          - uat
        environment:
          - SPRING_PROFILES_ACTIVE=uat
        depends_on:
          - some_image
    
      adapter-dev:
        extends:
          file: common-services.yml
          service: adapter
        profiles:
          - dev
        environment:
          - SPRING_PROFILES_ACTIVE=dev
        depends_on:
          - some_image