2

Trying to optimize definition of multiple services with docker-compose.yml

Here is the original, "dumb" variant of the docker-compose.yml:

version: '3'
services:
  s1:
    build: .
    ports:
    - "5001:9000"
    volumes:
    - ../www1:/var/www
  s2:
    build: .
    ports:
    - "5002:9000"
    volumes:
    - ../www2:/var/www
  s3:
    build: .
    ports:
    - "5003:9000"
    volumes:
    - ../www3:/var/www

Is there some sort of an iterator to compact this to just one block like the following?

version: '3'
services:
  for i in 1,2,3:
    s$i:
      build: .
      ports:
      - "500$i:9000"
      volumes:
      - ../www$i:/var/www
2

Not in pure Docker Compose. If you have a plain-text templating engine you like (Mustache, Jinja, m4, ...) you can ask it to do this for you.

You tagged this as , and Compose can take the YAML configuration on stdin, so in principle one option is to write a shell script, and then pipe that into docker-compose:

#!/bin/sh

buildComposeYaml() {
  cat <<HEADER
version: '3'
services:
HEADER
  for i in $(seq 3); do
    cat <<BLOCK
  s$i:
    build: ../www$i
    ports:
      - "500$i:9000"
BLOCK
  done
}

buildComposeYaml | docker-compose -f- "$@"

(Note that YAML is indentation-sensitive, and the script is mixing indentation for the script itself, the YAML embedded in the script, and the end-of-heredoc markers; so this will work for a simple tool but it wouldn't be my long-term choice.)

2
  • Nice. I also had an idea to use a templating engine, like jinja2 in Ansible. May 7 '20 at 23:44
  • The issue with external processes generating configuration is difficulty incorporating the approach into CM. And also, docker-compose is likely to have harder time determining if configuration has undergone changes and containers need to be updated. May 7 '20 at 23:50
2

Using docker-compose version 3.3 extensions and with the long variants for ports & volumes:

version: '3.3'
services:
  s1: &s
    build: .
    ports:
    - published: 5001
      target: 9000
    volumes:
    - source: ../www1
      target: /var/www
  s2:
    <<: *s
    ports:
    - published: 5002
    volumes:
    - source: ../www2
  s3:
    <<: *s
    ports:
    - published: 5003
    volumes:
    - source: ../www3

Not really more compact, but native :-)

Version 3.4 introduced further improvements into making docker-compose.yml more DRY.

Perhaps someone more experienced will point to even greater developments yet!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.