Home > Enterprise >  Can I run multiple instances of a service in docker-compose
Can I run multiple instances of a service in docker-compose

Time:10-08

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

CodePudding user response:

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.

CodePudding user response:

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?

  • Related