Search code examples
dockerdocker-composereplication

How to specify number of containers using docker-compose without --scale?


In my docker-compose I have multiple client and worker classes, specifically a client of type A, one of type B and another of type C, with their respective worker classes. Every time I execute docker-compose I need to use the option --scale a total of 6 times if I want to use a number of containers different to 1 for each class: --scale cliA=2 --scale cliB=3 [...]. Is there an alternative to having classes on my docker-compose.yml and instead have an unified class for a client which could be scaled differently for each different class (and the same for the worker)?

I have reasoned about it, and I have come to the conclusion that it may be possible to do something like this (check the code at the end of the question for reference on the cli class):

cli:
  image: client
  // More stuff
  scale: 4
    environment:
      CLASSID=A
  scale: 2
    environment:
      CLASSID=B
  // [...]

This docker-compose.yml would be able to create classes as needed without the need of calling --scale every time. However, I have checked the reference for docker-compose but I haven't found anything that helps me. I found an insightful post which mentioned that I could use docker-swarm in order to accomplish this task, but I think it's out of the scope of the subject (this question is trying to answer an exercise).

Here is the code for the docker-compose.yml file:

version: '2'
services:
  cliA:
    image: client
    build: ./client/
    links:
      - bro
    environment:
      - BROKER_URL=tcp://bro:9998
      - CLASSID=A
  // Similar description for cliB, cliC; only CLASSID changes

  worA:
    image: worker
    build: ./worker/
    links:
      - bro
    environment:
      - BROKER_URL=tcp://bro:9999
      - CLASSID=A
  // Similar description for worB, worC; only CLASSID changes

  bro:
    image: broker
    build: ./broker/
    expose:
      - "9998"
      - "9999"

Any help is appreciated.


Solution

  • Services are a definition of how to run a container, along with all of the settings. If you need multiple containers running with different settings, you need different services. You can use the Yaml alias and anchor syntax to effectively copy one service to another and then apply changes, e.g.:

    version: "3"
    services:
      app1: &app1
        image: app
        environment:
          app: 1
      app2:
        <<*app1
        environment:
          app: 2
    

    Once you have broken your problem into multiple services, you can follow the advices from your linked question.


    I'm also seeing the possibility to use variables in your compose file. E.g.

    version: '2'
    services:
      cli:
        image: client
        build: ./client/
        links:
          - bro
        environment:
          - BROKER_URL=tcp://bro:9998
          - CLASSID=${CLASSID}
        scale: ${SCALE}
    

    And then you could deploy with various environment files:

    $ cat envA.sh
    CLASSID=A
    SCALE=4
    $ cat envB.sh
    CLASSID=B
    SCALE=2
    $ set -a && . ./envA.sh && set +a && docker-compose -p projA up
    $ set -a && . ./envB.sh && set +a && docker-compose -p projB up