116

In my docker compose file there is a dynamic field which I'd like to generate during the running. Actually it is a string template:

environment:
    - SERVER_URL:https://0.0.0.0:${PORT}

And I want to configure this PORT parameter dynamically

docker-compose run <service> PORT=443

In documentation there is ARGS parameters set I suppose I can use. But there is no information how can I use those inside compose file

dr11
  • 5,166
  • 11
  • 35
  • 77
  • have a look at https://docs.docker.com/compose/compose-file/#compose-documentation it seems to answer your question – user2915097 Apr 21 '17 at 13:56
  • 13
    this is solution is by environment variables. I want to use command line arguments instead – dr11 Apr 21 '17 at 13:58
  • Read [this answer](https://stackoverflow.com/questions/35796353/can-i-pass-arguments-into-docker-compose-the-command-config-option?answertab=active#tab-top) and its comments. – Zeinab Abbasimazar Aug 22 '17 at 06:24
  • 2
    I believe what OP requires is to be able to pass a value starting from docker-compose call. Try this answer https://stackoverflow.com/questions/35093256/how-do-i-pass-an-argument-along-with-docker-compose-up – Quirino Gervacio Feb 13 '19 at 08:48
  • It's possible to use an environment variable in docker-compose. It's a bit different that what i initially thought but works For more: https://docs.docker.com/compose/environment-variables/ – theredcap Sep 11 '22 at 15:32
  • The `ARGS` you refer to are arguments to `COMMAND`. It isn't anything that would be interpreted as arguments by `docker-compose run`. – Huliax Jan 03 '23 at 23:06
  • Very simple to do. See this answer: https://stackoverflow.com/a/62123142/1025695 – Huliax Jan 03 '23 at 23:17

8 Answers8

63

In docker-compose, arguments are available and usefull only in dockerfile. You can specify what you are doing in the level ahead like following:

#dockerfile
ARG PORT
ENV SERVER_URL "https://0.0.0.0:$PORT"

Your port can be set in your docker-compose.yml:

build:
  context: .
  args:
    - PORT=443

It is actually an environment variable in any case. You can pass it through your run command if that fits to you:

PORT=443 docker-compose run <service>
#or
docker-compose run <service> -e PORT=443
dzof31
  • 1,423
  • 1
  • 12
  • 20
  • 58
    This sucks, I want to be able to download a pre-built container and run it with whatever runtime arguments I choose. Being able to list them in docker-compose should be basic functionality. I'll just override the entrypoint. – Dagrooms Sep 25 '17 at 21:19
  • @Dagrooms I think this is possible with stack deploy. See my answer. – joshmcode Apr 19 '18 at 18:56
  • 6
    This worked for me and I did not have to touch my Dockerfile. I used `PORT=443 docker-compose ... -f bla.yml` to pass the port in and then in my YAML file, the line `command: bash -c "echo $PORT"` successfully displayed 443. – mareoraft Jul 03 '20 at 20:15
  • This does not seem to work anymore, unfortunately. - When using `MYARG=123 docker-compose run `, it returns "The terum MYARG=12345 is not recognized as a cmdlet name, function, script file or operating program." - When using `docker-compose run -e MYARG=123`, it returns "Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-e": executable file not found in $PATH: unknown" – LucianoBAF Sep 26 '22 at 13:35
  • 1
    The answer by @mareoraft worked perfectly and is the cleanest option imo. I think it should be turned into an actual answer so it doesn't get easily overlooked! – Nick Mar 02 '23 at 14:27
58

You can use the flag when using docker-compose build

docker-compose build --build-arg PRODUCTION=VALUE

In Dockerfile you can get the argument PRODUCTION

# Dockerfile
ARG PRODUCTION
FROM node:latest
blueandhack
  • 689
  • 5
  • 5
11

This is possible with docker stack deploy

Example Compose File in your environment section:

- MY_VARIABLE_NAME=${MY_VARIABLE_VALUE}

Stack Deploy Command (I ran this from Gitbash in Windows):

MY_VARIABLE_VALUE=some-value docker stack deploy --compose-file compose_file_here stackname

Reference See this Github post here

joshmcode
  • 3,471
  • 1
  • 35
  • 50
  • 2
    Worth noting that this works with `docker compose up` as well – Sych Dec 06 '22 at 16:27
  • 1
    All of these answers boil down to environment variables. Too bad one can't pass an argument to `docker-compose up` in such a way that the variable would be expanded when "executing" the docker compose, but would NOT be seen by the container. For example, a variable that specifies which version of the image to use to spin up a particular service. – Szczepan Hołyszewski Dec 22 '22 at 10:58
3

Sharing the only way I managed to set a runtime variable with Docker Compose using minimum setup and command changes.

On docker-compose.yml:

services:
  my_service:
    ...
    environment:
      - MYENVVAR=placeholder_value

On the terminal:

docker-compose run -e MYENVVAR=actual_value my_service

Please pay attention that the "-e" portion of the command line argument must come before the service name.

This is described on the official documentation: Set environment variables with docker compose run

LucianoBAF
  • 189
  • 2
  • 6
2

This worked for me and I did not have to touch my Dockerfile:

I used

PORT=443 docker-compose ...(whatever)... -f bla.yml

to pass the port in and then in my YAML file, the line command: bash -c "echo $PORT" successfully displayed 443.

mareoraft
  • 3,474
  • 4
  • 26
  • 62
1

This is possible with docker-compose with ARGS inside Dockerfile.

Problem to Solve:

  • Pull changes from Git Respository, to Automate App Deploy

Dockerfile

RUN 
ARG CACHEBUST=1 # This will setup a arg called CACHEBUST
RUN  git clone

Run the below bash command to build and run. SETTING --build-arg CACHEBUST= random md5sum hash, makes Docker-Compose to rebuild the image, starting the line with ARGS and so on.

docker-compose -f dockerprd.yml build  --build-arg CACHEBUST=$(echo $RANDOM | md5sum | head -c 20; echo;) && docker-compose -f dockerprd.yml up -d
0

The solution that I found for this problem was to dynamically create an env file and pass it as --env-file value.

I created a bash script:

$PROJ=$1
echo "REST_URL=http://$2" > ./docker-env-$PROJ
echo "BRANCH=$3" >> ./docker-env-$PROJ

docker compose \
      -p $PROJ \
      --env-file ./docker-env-$PROJ \
      up -d

rm -f ./docker-env-$PROJ

and run it:

start_all.sh mycont "localhost:8080" master

Sych
  • 1,849
  • 16
  • 19
0

We can pass the argument to docker compose like that: Run the docker-compose.yaml with this command:

$ ENV=staging docker-compose up

docker-compose.yaml file look like that:

...
go:
    container_name: mailavail_go
    build:
      context: ./go
      dockerfile: Dockerfile
      args:
        ENV: ${ENV} # we can defined arguments like that
    ports:
      - 8080:8080
...

Dockerfile file look like that:

...
FROM golang:latest

ARG ENV=dev # we can also add a default value

ENV ENV=${ENV} # this will set the value

echo "My ENV is ${ENV}" # This is for testing purpose and it will the ENV value

RUN mkdir /golang
...