1

For example, if I have a docker compose file and like the following:

version: '3.7'

services:
  my_app:
    image: my_app/image
    restart: always
    links:
      - mysql
  
  mysql:
    image: mysql
    restart: always

Is there a way to create and run more than 1 container of my_app without explicitly stating another one? The catch is, each app would use different env variables; each app instance would process for a different user accounts. This would be different from k8s as I'm not trying to scale horizontally. Or would I need to create a file like the following:

version: '3.7'

services:
  my_app1:
    image: my_app/image
    restart: always
    environment: 
      - ACCOUNT=1
      - ACCOUNT=2
      - ACCOUNT=3
    links:
      - mysql

  my_app2:
    image: my_app/image
    restart: always
    environment: 
      - ACCOUNT=4
      - ACCOUNT=5
      - ACCOUNT=6
    links:
      - mysql

  my_app3:
    image: my_app/image
    restart: always
    environment: 
      - ACCOUNT=7
      - ACCOUNT=8
      - ACCOUNT=9
    links:
      - mysql
  
  mysql:
    image: mysql

2 Answers 2

2

Neither Compose nor any other orchestration system I'm aware of has a way to directly declare several containers that are similar except where they're not. Some tools like the Kubernetes Helm tool can apply a templating engine that can generate YAML content, but this gets complicated quickly. For plain Compose, you need to list out all of the containers separately in the docker-compose.yml file.

In the file you've shown, the links: option is obsolete and unnecessary, and you can safely just remove it. If you do that then the only thing you're repeating between the different containers is the image: and restart: lines, which isn't bad.

One technique you'll see in more complex Compose files is to use the YAML merge key extension in combination with a Compose extension field to declare common fields. In your file this could look like:

version: '3.8'
x-common: &common
  image: my_app/image
  restart: always
services:
  my_app1:
    <<: *common
    environment:
      ACCOUNTS: '1,2,3'
  my_app2:
    <<: *common
    environment:
      ACCOUNTS: '4,5,6'
  mysql: {...}

The one big limitation of this is that the merge is not recursive. If every container needs an environment variable MYSQL_HOST=mysql but also the different containers need different ACCOUNTS, you'll have to repeat the entire environment: block for every service.

Sign up to request clarification or add additional context in comments.

Comments

0

AFAIK there is no "native" way. Since you would be changing only a few parts of the container definition the two possibilities I would consider is:

  1. As you said just create more container definitions. There you can use a for loop in a templating engine like Helm https://helm.sh/docs/chart_template_guide/control_structures/#looping-with-the-range-action

  2. For loop in your application. Unless it is too complicated, what is stopping you from passing in a list of the possible variables, and having a script that keeps starting the applications one by one?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.