Answers: <p>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.</p>
  
  <p>You tagged this as <a href="/questions/tagged/shell-script" class="post-tag" title="show questions tagged &#39;shell-script&#39;" rel="tag">shell-script</a>, and <a href="https://docs.docker.com/compose/reference/#specifying-multiple-compose-files" rel="noreferrer">Compose can take the YAML configuration on stdin</a>, so in principle one option is to write a shell script, and then pipe that into <code>docker-compose</code>:</p>
  
  <pre class="lang-sh prettyprint-override"><code>#!/bin/sh
  
  buildComposeYaml() {
    cat &lt;&lt;HEADER
  version: '3'
  services:
  HEADER
    for i in $(seq 3); do
      cat &lt;&lt;BLOCK
    s$i:
      build: ../www$i
      ports:
        - "500$i:9000"
  BLOCK
    done
  }
  
  buildComposeYaml | docker-compose -f- "$@"
  </code></pre>
  
  <p>(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.)</p>
  
Answers: CC BY-SA 4.0
Answers: 2020-05-07T23:44:18.290Z
Answers: Nice. I also had an idea to use a templating engine, like `jinja2` in `Ansible`.
Answers: Alexander Shcheblikin
Answers: CC BY-SA 4.0
Answers: 2020-05-07T23:50:44.243Z
Answers: 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.
Answers: Alexander Shcheblikin
Answers: CC BY-SA 4.0
Answers: 2020-04-12T12:20:05.320Z
Answers: 2020-04-12T12:20:05.320Z
Answers: David Maze
Answers: <p>Using <code>docker-compose</code> version 3.3 extensions and with the long variants for <code>ports</code> &amp; <code>volumes</code>:</p>
  
  <pre><code>version: '3.3'
  services:
    s1: &amp;s
      build: .
      ports:
      - published: 5001
        target: 9000
      volumes:
      - source: ../www1
        target: /var/www
    s2:
      &lt;&lt;: *s
      ports:
      - published: 5002
      volumes:
      - source: ../www2
    s3:
      &lt;&lt;: *s
      ports:
      - published: 5003
      volumes:
      - source: ../www3
  </code></pre>
  
  <p>Not really more compact, but native :-)</p>
  
  <p>Version 3.4 introduced <a href="https://medium.com/@kinghuang/docker-compose-anchors-aliases-extensions-a1e4105d70bd" rel="nofollow noreferrer">further improvements into making docker-compose.yml more DRY</a>. </p>
  
  <p>Perhaps someone more experienced will point to even greater developments yet!</p>
  
Answers: CC BY-SA 4.0
Answers: 2020-05-07T23:43:03.767Z
Answers: 2020-05-07T23:43:03.767Z
Answers: Alexander Shcheblikin
Body: <p>Trying to optimize definition of multiple services with <code>docker-compose.yml</code></p>
  
  <p>Here is the original, "dumb" variant of the <code>docker-compose.yml</code>:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Is there some sort of an iterator to compact this to just one block like the following?</p>
  
  <pre><code>version: '3'
  services:
    for i in 1,2,3:
      s$i:
        build: .
        ports:
        - "500$i:9000"
        volumes:
        - ../www$i:/var/www
  </code></pre>
  
Tags: <docker><docker-compose><yaml><shell-script><templating>
Title: docker-compose multiple services in a loop
UserDisplayName: Alexander Shcheblikin
ThreadText: # docker-compose multiple services in a loop
  
  (Asked by: username_0 on 2020-04-11)
  
  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
  
  ```
  
  **Tags:** docker, docker-compose, yaml, shell-script, templating
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2020-04-12. Score: 5
  
  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 [shell-script](/questions/tagged/shell-script "show questions tagged 'shell-script'"), and [Compose can take the YAML configuration on stdin](https://docs.docker.com/compose/reference/#specifying-multiple-compose-files), so in principle one option is to write a shell script, and then pipe that into `docker-compose`:
  
  ```sh
  #!/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.)
  
  > **Comments:**
  > **username_0**: Nice. I also had an idea to use a templating engine, like `jinja2` in `Ansible`.  
  > **username_0**: 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.  
  
  ---
  
  ### Answer by username_0 on 2020-05-07. Score: 3
  
  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](https://medium.com/@kinghuang/docker-compose-anchors-aliases-extensions-a1e4105d70bd).
  
  Perhaps someone more experienced will point to even greater developments yet!
  
  
  ---
  
  