You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@vdemeester I am just looking for the option docker stack deploy -e name=value stack_name, I gave an example of -c for reference here. (equivalent to env name=value docker stack deploy is what I have in mind.)
I am assuming that the variable in here docker stack deploy -c file.yml -e name=value stack_name will only be applicable to the service in the compose file. (It doesn't makes sense for to add a variable for the whole stack, my assumption is that variables are scoped to the service only, can they be scoped for the whole stack ?)
env SOME_VAR="I am some var" OTHER_VAR="I am other var" docker stack deploy -c docker-compose.yml envie
Inspecting environment variables on service one (envie_one):
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' envie_one
Shows:
[
"SOME_VAR=I am some var",
"baz=I am other var",
"foo=bar"
]
And its labels:
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Labels}}' envie_one
Shows:
{
"com.docker.stack.namespace": "envie",
"some-label": "I am some var"
}
Inspecting environment variables on service two (envie_two)
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' envie_two
[
"hello=world",
"world=I am some var"
]
And its labels:
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Labels}}' envie_two
Shows:
{
"com.docker.stack.namespace": "envie",
"some-label": "I am other var"
}
My take on this
Environment variables that are substituted while processing the docker compose file are already possible;
you can set them up-front (export MYVAR=myvalue)
you can set them inline (env MYVAR=myvalue)
What's not supported (yet?) is the use of an .env file when deploying stacks: moby/moby#29133. I'd personally be good with adding support for .env files, so that "environment" variables are set when deploying a stack, without the requirement to export those variables up-front (or set them manually on each run).
What I don't think should be done is add an --env foo=bar option that would set the foo=bar environment variable on each service in the stack. Reasons I think we should not be adding that:
The environment variable wil be set on every service in the stack: in many cases you may want to only set them on some services, but not on all
Changing those values will re-deploy every service in the stack (likely not desirable)
The docker-compose file is intended to be describing the definition of your services: by manually changing the service configuration (i.e., adding environment variables), the definition of the service in the docker compose file no longer matches the actual service. If you want an environment variable (or any other option) to be set on a service; edit the docker-compose file, and add it to the services.
What if I want an environment variable to be set on service(s), but don't store it's value in the docker-compose file?
Use variable substitusion, and set the environment-variable in your shell (having support for an .env file would help with this):
And see that the additional environment variables are set;
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' mystack_one
["debug=1","somevar=somevalue"]
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' mystack_two
["development=yes"]
Reacted by TheWingMan, olekyd, Tamlyn Rhodes, Andy Elliott, Adnn, Oleksandr Shmyrko, pierresomos, JleMyP, Anton Romanov, Kendry Grullón and 15 more
Reacted by Vincent Demeester, nerdybreed, Jacek Cała, Tavee Khunbida, Jepil Choi, Marco Tazzari, Alex Lopes, Tamlyn Rhodes, Alexander, anshupitlia and 11 more
Having said the above; I'm interested to hear what the exact use-case is that people here are looking for. Perhaps you can explain what you want to use this for, and show examples how it will be used.
Environment variables that are substituted when processing the docker compose file
Specifically, I have two files dev.env and prod.env for development and production that each export a bunch of variables. And when I run docker stack I do it like this:
Within those env files I also have the following for variables in common across prod and dev:
. ./shared.env
As long as the user remembers to source the file, it works great. It would be a little nicer to have support for multiple .env files, but the approach we have now seems to work.
Okay, so looks like the desired feature would be to (for a start) make docker stack deploy read an .envfile from the current directory (same as docker-compose up does).
This is by design. The .env support is a feature of Compose, not of the file format.
We can discuss adding this for a future release, but I don't know if it's really the best option.
Some questions, as I know there are various limitations to the current .env files;
Should we stick to the simple key=value syntax (no special treatment of quotes (", '") in values)?
Same: an .env file thus will not be useful for Bash/shell (i.e., export foo=bar won't work)
Same: variables inside the file won't be expanded (FOO=${BAR}-something will literally use ${BAR}-something as value for the FOO env-var)
In addition to the above, I think it would be useful to print an informational message that docker read variables from that file (so that it doesn't catch a user by surprise).
I'm busy with GDPR right now but will revisit this next week. I had a specific use case and will see how it fits in with the above. I expect setting environment variables on the command line might work for me but will confirm shortly.
I am using a standard docker-compose.yml file to define my stack. I wish to build the containers via "docker-compose build" and then deploy into my swarm via "docker stack deploy".
Due to way our CI/CD pipeline is setup, we explicitly tag all of our Docker images with the product release name and version. As Docker Compose supports environment variable substitution, I can define the "image" tags within the "build" section as follows:-
The result of the build is a suitably tagged image.
What I would like to happen is for the same docker-compose.yml file to support environment variable substitution via the call to "docker stack deploy" when deploying my stack such that the correct images are deployed. My workaround for now is to set those environment variables via the shell, but it would be good to see a way to set these on the command line call.
Happy to take advice if there is a better or more Docker compliant way of achieving this.
Reacted by Sune Brøndum Wøller, KajMagnus, Pascal Woerde, Haim Ari, Tummala Dhanvi, ISSAM BEN, Manash Sonowal, Ammar Najjar, jamshid, Ricardo Rover and 10 more
I'm deploying from CircleCI and have the same need as @gbjbaaha. Unfortunately it not as easy as exporting the variable to the environment because in CircleCI the docker environment is remote, so I'd have to ssh in and export them there. This requires a lot of setup because again the machine where the docker commands are executed is remote, see setup_remote_docker
There is this work around docker-compose config | docker stack deploy --compose-file - test That will create your docker-compose.yaml but replace with the variables from .env
Reacted by Micheal Taylor, CarlosVilla, magyarimn, Michael Kuck, Akshay Takalkar, Alexandre GV., Eddie, Thanos Nokas, Samuel Ting, Karl Iledan and 18 more
Reacted by Micheal Taylor, Michael Gardner, Lucas Henrique Teixeira Coelho Dias and Ricardo Rover
Reacted by Jean-Baptiste Martin and Lucas Henrique Teixeira Coelho Dias
Reacted by Micheal Taylor, Michael Kuck, Michael Gardner, Thanos Nokas, Lorenzo Calamandrei, Lucas Henrique Teixeira Coelho Dias, Ricardo Rover, Fajarullah, digitaloc, Gaetan Jonathan BAKARY and 2 more
How to force a container's (task) environment variables to receive its values from the environment variables of the host in which it is running? (This is for each task in a "docker stack deploy" running in several swarm nodes)
I have a service defined in a "docker-compose.yml" file, like:
But the expressions ${OL_ECOSYS_SRV} and ${OL_ECOSYS_DB_SRV} are evaluated at the moment of entering the command "docker stack deploy" in node A, so the different IP address effect depending on the node if not achieved, and all containers (tasks) in both nodes are created with the same IPs of node A because the variables are evaluated at the service creation moment and not at the task creation moment.
How could I pass to the containers in node A and B a different local dns configuration (/etc/hosts) depending on the node itself? Is there another approach to solve this problem?
This must work for a single but replicated docker swarm service.
There is this work around docker-compose config | docker stack deploy --compose-file - test That will create your docker-compose.yaml but replace with the variables from .env
Good workaround, but will not work in cases docker-compose is not installed, only docker is
There is this work around docker-compose config | docker stack deploy --compose-file - test That will create your docker-compose.yaml but replace with the variables from .env
Good workaround, but will not work in cases docker-compose is not installed, only docker is
My entire workflow is failing at this point with external networks defined on the docker-compose giving an error only if this method is used instead hardcoding configs. So this is failing parsing external networks or in any other way: docker-compose config -> the parsed definition contains your external-network-name: null and then docker deploy prints this error as a consecuence.
Additional property name is not allowed
I really don't know how to transition from docker-compose to Swarm, where you set a development and production scenarios.
How can you make this possible, when your docker-compose workflow is meant to reading ${VARIABLES} from .env file but you are not intended to use this approach when you are full on docker Swarm?
I just read about secrets but I want to define not secret configs from .env like hostnames and use secrets like passwords etc.. without the need of create secret manually for every ${VARIABLE} i was used to put in .env file when docker-compose times.
There is this work around docker-compose config | docker stack deploy --compose-file - test That will create your docker-compose.yaml but replace with the variables from .env
Good workaround, but will not work in cases docker-compose is not installed, only docker is
My entire workflow is failing at this point with external networks defined on the docker-compose giving an error only if this method is used instead hardcoding configs. So this is failing parsing external networks or in any other way: docker-compose config -> the parsed definition contains your external-network-name: null and then docker deploy prints this error as a consecuence.
Additional property name is not allowed
I really don't know how to transition from docker-compose to Swarm, where you set a development and production scenarios.
How can you make this possible, when your docker-compose workflow is meant to reading ${VARIABLES} from .env file but you are not intended to use this approach when you are full on docker Swarm?
REGISTRY=my-repo.registry.com
app.secret=set by env file
When I start this: docker stack deploy -c docker-compose.yml docker-test --with-registry-auth
All I get is: Invalid reference format.
This seems to be due to the $REGISTRY in the image tag. When I manually set the correct value in the docker-compose like image: my-repo.registry.com/docker-test:latest, everything works fine. Though there is still an $APP_SECRET variable to be resolved from .env, and that actually still works!
So why is does variable replacement works in environment tag, but not in image tag?
docker stack does not use .env files to set environment variables for the current environment (that feature is specific to Docker Compose). You need to make sure those environment variables are set when running the command, so that they're evaluated.
The env_file option in the compose-file is the equivalent of docker run --env-file, which allows setting environment variables on the container itself (it's the equivalent to setting --env FOO=bar --env BAR=baz on a container). Those environment variables are set on the container itself, but not used to interpolate environment variables in the compose-file itself.
(docker compose unfortunately also has a top-level --env-file flag, which is used to specify an alternative location for the .env file, which makes its quite confusing, but as that flag has existed for quite some time, it's difficult to remove it without potentially breaking many users)
Activity
dhanvi commentedon Mar 12, 2018
From @AkihiroSuda on March 11, 2018 14:16
CLI is out of the scope of this repo.
Please refer to https://github.com/docker/cli
mallchin commentedon Apr 26, 2018
jeanadrien commentedon May 18, 2018
vdemeester commentedon May 18, 2018
@dhanvi Thanks for the issues. That said, I have a small question about the feature request
I can see two different features requested here :
${name}), this is then equivalent toenv name=value docker stack deploy@marcel-steinbach-mpf @jeanadrien @mallchin it would be helpful for us to know which one is it 👼 🙏
dhanvi commentedon May 18, 2018
@vdemeester I am just looking for the option
docker stack deploy -e name=value stack_name, I gave an example of -c for reference here. (equivalent to env name=value docker stack deploy is what I have in mind.)I am assuming that the variable in here
docker stack deploy -c file.yml -e name=value stack_namewill only be applicable to the service in the compose file. (It doesn't makes sense for to add a variable for the whole stack, my assumption is that variables are scoped to the service only, can they be scoped for the whole stack ?)thaJeztah commentedon May 22, 2018
@vdemeester's question was because there are two "levels" of environment variables:
For example, taking this
docker-compose.yml:Inspecting environment variables on service
one(envie_one):docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' envie_oneShows:
And its labels:
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Labels}}' envie_oneShows:
{ "com.docker.stack.namespace": "envie", "some-label": "I am some var" }Inspecting environment variables on service
two(envie_two)docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Env}}' envie_twoAnd its labels:
docker service inspect --format='{{ json .Spec.TaskTemplate.ContainerSpec.Labels}}' envie_twoShows:
{ "com.docker.stack.namespace": "envie", "some-label": "I am other var" }My take on this
Environment variables that are substituted while processing the docker compose file are already possible;
export MYVAR=myvalue)env MYVAR=myvalue)What's not supported (yet?) is the use of an
.envfile when deploying stacks: moby/moby#29133. I'd personally be good with adding support for.envfiles, so that "environment" variables are set when deploying a stack, without the requirement to export those variables up-front (or set them manually on each run).What I don't think should be done is add an
--env foo=baroption that would set thefoo=barenvironment variable on each service in the stack. Reasons I think we should not be adding that:What if I want an environment variable to be set on service(s), but don't store it's value in the docker-compose file?
Use variable substitusion, and set the environment-variable in your shell (having support for an
.envfile would help with this):Now, deploy the stack using either:
export SOME_VAR=some-value docker stack deploy -c docker-compose.yml foobarOr
What if I want additional environment variables to be set (in some situations)
For example: during development, I want to set some additional environment variables, but in production, I don't want those set (or vice-versa).
Use an "override" file, by deploying multiple docker compose files:
docker-compose.yml:docker-compose-dev.yml:Specify both files when deploying the stack:
And see that the additional environment variables are set;
thaJeztah commentedon May 22, 2018
Having said the above; I'm interested to hear what the exact use-case is that people here are looking for. Perhaps you can explain what you want to use this for, and show examples how it will be used.
jgoodall commentedon May 22, 2018
My use case is the first one you describe:
Specifically, I have two files
dev.envandprod.envfor development and production that each export a bunch of variables. And when I rundocker stackI do it like this:Or,
Within those
envfiles I also have the following for variables in common across prod and dev:As long as the user remembers to source the file, it works great. It would be a little nicer to have support for multiple
.envfiles, but the approach we have now seems to work.thaJeztah commentedon May 22, 2018
Thanks for the additional information!
Okay, so looks like the desired feature would be to (for a start) make
docker stack deployread an.envfile from the current directory (same asdocker-compose updoes).From moby/moby#29133 (comment), I see that @dnephin was open to discuss that option, but looks like he had some reservations;
Some questions, as I know there are various limitations to the current
.envfiles;key=valuesyntax (no special treatment of quotes (",'") in values)?.envfile thus will not be useful for Bash/shell (i.e.,export foo=barwon't work)FOO=${BAR}-somethingwill literally use${BAR}-somethingas value for theFOOenv-var)In addition to the above, I think it would be useful to print an informational message that docker read variables from that file (so that it doesn't catch a user by surprise).
mallchin commentedon May 23, 2018
I'm busy with GDPR right now but will revisit this next week. I had a specific use case and will see how it fits in with the above. I expect setting environment variables on the command line might work for me but will confirm shortly.
gbjbaaha commentedon Jul 20, 2018
I have a slightly different scenario:-
I am using a standard docker-compose.yml file to define my stack. I wish to build the containers via "docker-compose build" and then deploy into my swarm via "docker stack deploy".
Due to way our CI/CD pipeline is setup, we explicitly tag all of our Docker images with the product release name and version. As Docker Compose supports environment variable substitution, I can define the "image" tags within the "build" section as follows:-
The result of the build is a suitably tagged image.
What I would like to happen is for the same docker-compose.yml file to support environment variable substitution via the call to "docker stack deploy" when deploying my stack such that the correct images are deployed. My workaround for now is to set those environment variables via the shell, but it would be good to see a way to set these on the command line call.
Happy to take advice if there is a better or more Docker compliant way of achieving this.
b01 commentedon Aug 7, 2018
I'm deploying from CircleCI and have the same need as @gbjbaaha. Unfortunately it not as easy as exporting the variable to the environment because in CircleCI the docker environment is remote, so I'd have to ssh in and export them there. This requires a lot of setup because again the machine where the docker commands are executed is remote, see setup_remote_docker
sadok-f commentedon Sep 25, 2018
2 remaining items
kajmagnus commentedon Nov 16, 2018
Ok thanks @gbjbaaha for the info :- )
mtazzari commentedon Dec 3, 2018
gerbil commentedon Dec 13, 2018
yisraeldov commentedon May 20, 2019
There is this work around
docker-compose config | docker stack deploy --compose-file - testThat will create yourdocker-compose.yamlbut replace with the variables from.envejyanezp commentedon Nov 26, 2019
Another use case:
How to force a container's (task) environment variables to receive its values from the environment variables of the host in which it is running? (This is for each task in a "docker stack deploy" running in several swarm nodes)
I have a service defined in a "docker-compose.yml" file, like:
This service is to be deployed unto two nodes of a docker swarm using docker stack deploy
For each node I have defined the environment variables:
But the expressions
${OL_ECOSYS_SRV}and${OL_ECOSYS_DB_SRV}are evaluated at the moment of entering the command "docker stack deploy" in node A, so the different IP address effect depending on the node if not achieved, and all containers (tasks) in both nodes are created with the same IPs of node A because the variables are evaluated at the service creation moment and not at the task creation moment.How could I pass to the containers in node A and B a different local dns configuration (/etc/hosts) depending on the node itself? Is there another approach to solve this problem?
This must work for a single but replicated docker swarm service.
Which approach would you use?
anshupitlia commentedon Jun 4, 2020
Good workaround, but will not work in cases docker-compose is not installed, only docker is
yamac-kurtulus commentedon Aug 2, 2020
@ejyanezp
Hey man, did you manage to find an approach for your use case?
moracabanas commentedon Jan 1, 2021
My entire workflow is failing at this point with external networks defined on the
docker-composegiving an error only if this method is used instead hardcoding configs. So this is failing parsing external networks or in any other way:docker-compose config-> the parsed definition contains yourexternal-network-name: nulland thendocker deployprints this error as a consecuence.I really don't know how to transition from docker-compose to Swarm, where you set a development and production scenarios.
How can you make this possible, when your docker-compose workflow is meant to reading ${VARIABLES} from
.envfile but you are not intended to use this approach when you are full on docker Swarm?moracabanas commentedon Jan 1, 2021
I just read about secrets but I want to define not secret configs from
.envlike hostnames and use secrets like passwords etc.. without the need ofcreate secretmanually for every ${VARIABLE} i was used to put in .env file when docker-compose times.moracabanas commentedon Jan 2, 2021
My workaround:
deploy.sh:(stack_name optional if previously defined in .env)
ejyanezp commentedon Jan 6, 2021
Nope :(
kodyrecords commentedon Apr 6, 2022
How can I pass an environment variable for the image registry from
gitlab_citodocker-composefor use withdocker swarm?In my following example, the value
$APP_SECRETis successfully resolved from a.envfile, while$REGISTRYis not!.gitlab_ci.yml:(even setting the
env REGISTRY=...does not work here. And also not when completely removing that statement).docker-compose.yml:.env:When I start this:
docker stack deploy -c docker-compose.yml docker-test --with-registry-authAll I get is:
Invalid reference format.This seems to be due to the
$REGISTRYin theimagetag. When I manually set the correct value in the docker-compose likeimage: my-repo.registry.com/docker-test:latest, everything works fine. Though there is still an$APP_SECRETvariable to be resolved from.env, and that actually still works!So why is does variable replacement works in
environmenttag, but not inimagetag?thaJeztah commentedon Apr 6, 2022
docker stackdoes not use.envfiles to set environment variables for the current environment (that feature is specific to Docker Compose). You need to make sure those environment variables are set when running the command, so that they're evaluated.Using this compose file:
And a stack deploy with the
REGISTRYandAPP_SECRETenvironment variables set:kodyrecords commentedon Apr 6, 2022
But why then does
env_file: '.env'set the$APP_SECRETinenvironmenttag successfully?thaJeztah commentedon Apr 6, 2022
The
env_fileoption in the compose-file is the equivalent ofdocker run --env-file, which allows setting environment variables on the container itself (it's the equivalent to setting--env FOO=bar --env BAR=bazon a container). Those environment variables are set on the container itself, but not used to interpolate environment variables in the compose-file itself.(docker compose unfortunately also has a top-level
--env-fileflag, which is used to specify an alternative location for the.envfile, which makes its quite confusing, but as that flag has existed for quite some time, it's difficult to remove it without potentially breaking many users)