Colin FAY
Colin FAY

Reputation: 5109

Launch a docker-compose service several times with different variables

I have a docker-compose with a service I'd love to launch several times with various env variables. The idea is to launch the service several times, notably on a series of ports.

My current strategy is to copy and paste the service name N times, N being the number of time I need to launch the service, but that seems very unefficient.

Reproducible example:

app/app.js

var http = require('http');

var name = process.env.NAME || "Jack"
var port = process.env.PORT || 1234

var server = http.createServer(function(req, res) {
    res.writeHead(200);
    res.end(`Hi ${name}!`);
});
server.listen(port, () => console.log(`Running on port ${port}`));

app/Dockerfile

FROM node:10

WORKDIR /usr/src/app

COPY . .

CMD [ "node", "app.js" ]

docker-compose.yml

version: '2'

services:
    node:
        build: app
        environment:
            - NAME=${NAME}
            - PORT=${PORT}
        command: node app.js
        expose:
            - "${PORT}"
        ports:
            - "${PORT}:${PORT}"

What I want to do is to be able to do :

And I now have two services, one on each port. localhost:1234 show "hello joe", localhost:1235 "Hello jack". Right now if I do that the same service is relaunched.

Things I have tried so far:

Upvotes: 4

Views: 1406

Answers (2)

smashraf24
smashraf24

Reputation: 11

https://docs.docker.com/compose/environment-variables/

As you can see the mentioned link you need to create you need to have a .env file at the same level as your compose file .

Now to run your same compose file multiple time without changing the parameters manually create a sample file say sample_file with your env variable as key value like "Key1=value_1" "key2=value_2" Now use sed to replace value_1 and value_2 and create a new file with .env and pipe the command with docker compose up -d

"sed -i -e 's/value_1/1234/g' -e 's/value_2/Joe/g' sample_file>sample_file.env|docker-compose up -d node"

Upvotes: 0

David Maze
David Maze

Reputation: 158976

If you can launch all of the containers in the same docker-compose.yml file then you can trim down a couple of options to make the amount of syntax more palatable.

There's no specific requirement that the process inside a container listen on the same port that's being published on the host, and in modern Docker expose: means almost nothing. That means you don't specifically need to configure a PORT environment variable; you can always start the container process on its default port 1234 and just remap that per-container. You also don't need to repeat the default CMD from the Dockerfile.

So an all-in-one Docker Compose setup for what you show could look like

version: '3' # 2 vs. 3 doesn't really matter here
services:
  joe:
    build: app
    environment:
      - NAME=joe
    ports: '1234:1234'
  jack:
    build: app
    environment:
      - NAME=jack
    ports: '1235:1234'

If you want to use a series of docker-compose invocations as you've shown, Compose has an internal notion of a "project", and it keeps track of the state of the containers in a project. By default the current directory's local name is used as the project name. In your docker-compose up command, Compose sees that you've changed the port mapping and environment settings for the node container in the same single project, so it replaces the existing container.

To tell Compose that there are different projects, you need the docker-compose -p option

NAME=joe PORT=1234 docker-compose -p joe up -d node
NAME=jack PORT=1235 docker-compose -p jack up -d node

Note that you will need to repeat this option on every docker-compose command invocation. If you use non-Compose commands like docker ps you will be able to see the project name included as part of the container name (joe_node_1, jack_node_1).

Upvotes: 1

Related Questions