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
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 theimage:
andrestart:
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:
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 differentACCOUNTS
, you’ll have to repeat the entireenvironment:
block for every service.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:
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
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?