moby: `docker stack deploy` in 1.13 doesn't load `.env` file as `docker-compose up` does
To test docker stack deploy --compose-file
function, I load one of my sample docker-compose.yml
:
version: '3'
services:
nginx:
image: "${DOCKER_USER}/lnmp-nginx:v1.2"
build:
context: .
dockerfile: Dockerfile.nginx
ports:
- "80:80"
networks:
- frontend
depends_on:
- php
php:
image: "${DOCKER_USER}/lnmp-php:v1.2"
build:
context: .
dockerfile: Dockerfile.php
networks:
- frontend
- backend
environment:
MYSQL_PASSWORD: Passw0rd
depends_on:
- mysql
mysql:
image: mysql:5.7
volumes:
- mysql-data:/var/lib/mysql
environment:
TZ: 'Asia/Shanghai'
MYSQL_ROOT_PASSWORD: Passw0rd
command: ['mysqld', '--character-set-server=utf8']
networks:
- backend
volumes:
mysql-data:
networks:
frontend:
backend:
In the image
section of service nginx
and php
, I used ${DOCKER_USER}
to get the docker id from environment variables. And if I use docker-compose up
, it will load .env
file as default envvar files, which content is:
DOCKER_USER=twang2218
However, if I use docker stack
to deploy this docker-compose.yml
, I will got following errors:
$ docker stack deploy --compose-file docker-compose.yml lnmp
Ignoring unsupported options: build
Creating network lnmp_frontend
Creating network lnmp_backend
Creating network lnmp_default
Creating service lnmp_php
Error response from daemon: rpc error: code = 3 desc = ContainerSpec: "/lnmp-php:v1.2" is not a valid repository/tag
As you can see, as docker stack deploy
command didn’t load .env
file, the ${DOCKER_USER}
was replaced by empty string, which cause image name become invalid.
If .env
file was loaded, the final image name should be twang2218/lnmp-php:v1.2
.
The environment substitution is actually working, if I run the command this way:
$ DOCKER_USER=twang2218 docker stack deploy --compose-file docker-compose.yml lnmp
Ignoring unsupported options: build
Creating network lnmp_frontend
Creating network lnmp_backend
Creating network lnmp_default
Creating service lnmp_mysql
Creating service lnmp_nginx
Creating service lnmp_php
And we can verify it’s working by docker service inspect
command:
$ docker service inspect lnmp_php | grep Image
"Image": "twang2218/lnmp-php:v1.2@sha256:4f1aef1350aeef3f757f6b6da8f2e1a79ff849f61382320e4b668bfe2b0d1c5a",
The image name is twang2218/lnmp-php:v1.2
, which is correct.
I tested this feature on Digtial Ocean droplet, which installed docker 1.13.0-rc2 via docker-machine
.
Here is the version:
$ docker version
Client:
Version: 1.13.0-rc2
API version: 1.25
Go version: go1.7.3
Git commit: 1f9b3ef
Built: Wed Nov 23 06:32:39 2016
OS/Arch: linux/amd64
Server:
Version: 1.13.0-rc2
API version: 1.25
Minimum API version: 1.12
Go version: go1.7.3
Git commit: 1f9b3ef
Built: Wed Nov 23 06:32:39 2016
OS/Arch: linux/amd64
Experimental: false
Here is the docker info
:
root@d1:~/docker-lnmp# docker info
Containers: 7
Running: 1
Paused: 0
Stopped: 6
Images: 4
Server Version: 1.13.0-rc2
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 43
Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: active
NodeID: vyf3mgcj3uonrnh5xxquasp38
Is Manager: true
ClusterID: jb8rxvd6ptrn3psfkiixxed7r
Managers: 1
Nodes: 3
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 3
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Node Address: 138.197.195.206
Manager Addresses:
138.197.195.206:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 03e5862ec0d8d3b3f750e19fca3ee367e13c090e
runc version: 51371867a01c467f08af739783b8beafc154c4d7
init version: 949e6fa
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 4.4.0-51-generic
Operating System: Ubuntu 16.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.5 MiB
Name: d1
ID: E6UB:PHX6:I2KY:Q35T:PCCI:MFDQ:ZMMN:2X7K:DEOZ:PAP7:4BUC:FP6X
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
provider=digitalocean
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 153
- Comments: 110 (14 by maintainers)
I don’t think the CLI is ever going to add
.env
support. Thedocker stack deploy
command was originally built with Distributed Application Bundle files in mind (hence the--bundle-file
option). DAB files were generated by Docker Compose with thedocker-compose bundle
command..env
and other Compose features would be handled bydocker-compose
, before being passed todocker stack deploy
. Direct support for Compose files indocker stack deploy
was always more of a compromise.The original promise of DAB files now lives on in Docker App, which also does not process
.env
.I have my developers use
docker-compose config
to pre-process Docker Compose projects before passing them todocker stack deploy
. You can do this in one line with:That way, all Docker Compose features including
.env
processing are fully applied.@whoan I’m using this as a workaround:
That way, variables don’t get stuck on the terminal window
The
.env
support is quite useful in Compose, we used it in many of our compose files. It separates dynamic parts and static parts ofdocker-compose.yml
file. With load.env
by default, we can just provides different.env
file for different environments, and keeping thedocker-compose.yml
and related scripts static.It’s not possible to use
env_file
orenvironment
indocker-compose.yml
to achieve the same envvars substitution result..env
is the most easy way to do it.Otherwise, we have to prefix
export
in each line of.env
file and manuallysource .env
every time before loading thedocker-compose.yml
, and the extra steps sometimes are prone to mistake.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.
EDIT: I hope this post doesn’t come across aggressively. I love the Docker Stack concept and I do think the whole Docker suite is pretty well supported. It just seems that Docker (the organisation) currently doesn’t view its products the same way users do, which is unfortunate and appears to be the cause of most issues I’ve run into using Compose and Stack.
I feel like this statement reveals a fundamental disconnect between the way Docker’s developers and users view these products. As a user, whether I’m working with Docker Engine, Docker Compose or Docker Swarm, it’s all Docker and should behave consistently as far as possible.
My understanding of the purpose of these products is:
One of the key selling points of Docker (and containers in general) is easy reuse of the same app in multiple environments. Therefore, Compose should be additive to Engine and Stack should be additive to Compose. Particularly as they share the same file format, Stack not supporting features of Compose leads to confusion for developers and added complexity in CI processes.
Just specify the .env file in your docker-compose.yml and it works:
See https://stackoverflow.com/questions/44694640/docker-swarm-with-image-versions-externalized-to-env-file
This confused me like crazy. My app would come up using docker-compose, but not with docker stack deploy. There should at least be a disclaimer prominently displayed in the docs
But IMO this is a bug, and is degrading the docker experience.
This is ridiculous. I just spent all day trying to get this to work. A disclaimer is at least needed somewhere in the docs that .env is not read by
docker stack
commands.sigh
It’s been two years and we are still like that… I don’t want to come across as rude, but come on! It’s matter of reusing a bit of code from docker-compose!
@dnephin : you state that .env is not part of the docker compose file format. However, the .env file feature is documented in the Compose file version 3 reference: https://docs.docker.com/compose/compose-file/#variable-substitution . This gives the impression .env also should work with docker stack deploy. Besides that, as already mentioned by others, separating actual environment specific values from the stack definition yaml is a much wanted/needed feature. Specifically we want to use it to specify image versions and replications.
It’s incredibly dumb that docker doesn’t support this yet.
+1 docker stack deploy should really support --env-file. Myself I’m struggling with re-using the same .yml file to deploy different stacks for development/test/production environments and I don’t want to deal with some fiddly export/sourcing of environment variables prior to deploying the stack. This is very error-prone (and a pain in the a** too to remember the exact commands each time). In my particular case I e.g. want to set different index-names (elasticsearch) per environment - but the rest of the config stays the same. This has nothing to do with “secrets” as mentioned in earlier posts. There seems to be a real need for --env-file for docker stack deploy based on the comment history above but sadly the Docker developers don’t seem to see that.
I am using a bash function as a workaround.
You may adapt it to your needs until the
secrets
feature be released:To summarize, for people like me, who have read this so far:
docker stack deploy
supports “Variable Substitution” but you need to set the environment variables from the.env
file in some way. Several options have been explained above. One of the neatest workarounds is usingdocker-compose config
as pre-processor. So you can create your stack withdocker stack deploy -c <(docker-compose config) STACK_NAME
.env_file
parameter in thedocker-compose.yml
file will set the environment variables in the created container and not on thedocker-compose.yml
file itself (and hence it cannot be used as an alternative to “Variable Substitution”).Update:
I was corrected by @thaJeztah.
Just
. .env
before callingdocker stack deploy
does not help, $variables are not substituted. Onlyenv .. xargs
trick did help. It would be nice to have--env-file=FILE
option like indocker run
.BEWARE of the
<(docker-compose -f CUSTOM-COMPOSE-FILENAME.yml config
HACK!!! The output ofdocker-compose config
anddocker-compose -f myfile.yml config
is NOT necessarily the same! The latter sometimes wraps env variables in extra quotes, so the output will be wrong!Example:
instead of
Is this issue tracked somewhere already?
.env file
source .env && docker stack deploy
It will also work with
docker-compose up
for bash@andyfinch Alternatively:
or:
set -a
adds the export attribute to every variable that gets created.set +a
restores the default behavior.@akhildangore please don’t comment on issues with questions that are not directly related. The
docker stack deploy
feature, by design does not perform builds. Reason for this is that a build is performed on the host that the command is run from, so the image will only be available on that node. When deploying that image in a Swarm, the service cannot be started on other nodes. To deploy services, make sure the image you’re deploying is pushed to a registry (or for testing; make sure the image is available on every node in the swarm)docker stack deploy -c <(docker-compose -f docker-compose-frpc-swarm-traefik.yml config) traefik
I would love if
.env
files were read by default like in Docker Compose and--env-file
(short-e
) would be added fordocker stack deploy
to be able to override environment variables and the defaults from the.env
file.docker stack deploy
can take a generated file. This works in bash for all my variables and keeps secrets secret as well:docker stack deploy --with-registry-auth --compose-file=<(ENV1=value1 ENV2=value2 docker-compose -f docker-compose.yaml -f docker-compose.override.yaml -f third-sample-compose.yaml config) stack-name
Please note I added the in-line ENV variables as additional ones or overrides. My compose files reference .env files and this works. Hope this is helpful 👍
The functionality of
docker-compose config
is what ties this together.Try this:
echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_name
It uses docker-compose to parse the config file, substituting env vars, strips warnings from the output and then pipes it to docker stack deploy via stdin. Replace ‘-f stack.yml’ with the name of your config file or omit it to use the default docker-compose.yml.
env_file: /path/to/env/file
noti just saw this from another post and I can only speculate why it works (same as your speculation) but we need confirmation as to why this is working as docker explicitly mentioned in the docu that env_file doesnt work.
@cjancsar They do. The documentation says:
oh, wow. I joined the confusion and pain while evaluating docker swarm for a big project as well. The secrets are all fun and games, just that not all external docker images support reading secrets from files. I do not want to modify for each of them and place a custom image. Might use them for my projects, yes, but for external projects would be a no go. So that leaves env variables. But hey, they behave differently from compose to stack! Imagine my surprise when I noticed that they don’t really work. How is it possible to have docker stack without env support?best would be in my opinion --env-file=dev.env , so it wouldn’t interfere with other env files… but the support for this is horrible. I must go back to k8s unfortunately, as the stack missing this from the start, could prove to be a horrible choice while in production, who knows how many other things will be missing.
There is a workaround if you don’t want to remember custom commands to do variable substitution in
docker stack deploy
. Add the following function to ~/.bashrc to the very end of the file and open bash again to enact those changes:The script does the following:
loadenvs
envfile
and assign the first argument to the function to it; if there is no argument, use ‘.env’ insteadenvfile
with the current shell; revert default exportability back to defaultsThen the usage is very simple:
loadenvs && docker stack deploy...
loadenvs .custom_env && docker stack deploy...
Please note that if you are using
sudo
to run docker commands, you need to use-E
option to preserve environmental variables in sudo session like that:loadenvs && sudo -E docker stack deploy...
This works like a charm, keep in mind if your compose file does not have the “docker-compose.yml” name your command should include the actual compose file name.
docker stack deploy -c <(docker-compose -f CUSTOM-COMPOSE-FILENAME.yml config) CUSTOM-STACK
It’s always nice to have the ability to load things from a
.env
file - apart from a simpler Docker secrets use-case which can now be circumvented, there are always Docker Compose values that you don’t want to have hardcoded in your repo.Let’s assume you use
docker stack deploy
to deploy a complete stack and you have the following requirements:If you can’t configure this with a
.env
file, you need to manually change thedocker-compose.yml
file before deploying the stack each time, otherwise the service scale value will revert back to 1.You can extend the above with things like networks, configuring the DNS that a service should listen to, etc.
I can draft a PR that will load a
.env
file, if one exists in the same directory asdocker-compose.yml
if we believe the above uses cases make sense.Hello All,
Docker version: v1.13.0-rc4
I am getting error : Ignoring unsupported options: build, Does it mean it will not create build from Dockerfile ?
And also getting same error for network_mode: Ignoring unsupported options: network_mode.
Below is command: DOCKER_IMAGE=akhil123 docker stack deploy -c docker-compose.yml foo
Many thanks in advance.
In docker compose V2 this approach won’t work causing
unsupported Compose file version: 1.0
error. (see https://github.com/docker/compose/issues/8950) This happens because nowconfig
command trimmsversion
field.It seems to me that the creators did it on purpose to even take away these hacks we had 🥇 😸
This should be more clear in the documentation. Although it’s called out that .env is not supported in the Variable Substitution section per @lengxuehx, it is not mentioned that env_file is ignored for stack deploys.
Another workaround is:
set -a && . .env && set +a && docker stack deploy...
.Just ran into the same thing as we are trying out swarm. I’ve read through all of the messages in various threads and am left extremely frustrated. IMO, some really good points and strong arguments were made by @ntwrkguru and others. I hope we can consider them to get this feature in; hacks won’t cut it.
+1 this would be really useful. Don’t see a downside really.
Having environment variable interpolation in deploy is the best solution for continuous integration.
One issue with the use of ‘.env’ is that it overlaps with similar file names used by, for example, Ruby on Rails, having the ability to specify an environment file by argument is superior.
@ntelisil’s suggestions are well taken, they could be supplemented or modified by:
https://unix.stackexchange.com/questions/294835/replace-environment-variables-in-a-file-with-their-actual-values:
I used:
And that worked fine, but I needed to add 3Mb or so to my container.
For those subscribing to this issue; secrets support for docker-compose files will be included in the 1.13.1 release, which should be not too far in the future
@vovimayhem no decision was made yet on
.env
file, but you may be interested in https://github.com/docker/docker/pull/30144, which adds support for secrets to the compose fileWe need an answer about this
That would only work for bash and not other shells.
+1
I wouldn’t say compose is for dev and stack for prod, necessarily. I view compose as being for a multi-container application or “system” and stack for multi-host deployments using swarm-mode as the scheduler/orchestrator. Otherwise, your comment is 100% spot on. I also am frustrated (if it weren’t obvious by my other comments) that there is a disconnect between the developers and the users as to how the product(s) are being used.
This still works as an alternative;
You don’t seem to get it @vovimayhem. I’m not talking about passing envs to containers; that works as expected. What I mean is to use an env_file that is parsed during
stack deploy
as it was duringcompose up
.docker stack deploy
does support variable substitution, but does not evaluate the.env
file; in the example below,HELLO_VERSION
is set tolinux
, and the service will use thehello-world:linux
tag (instead of the defaulthello-world:latest
)The
env_file
serves a different purpose (and is the equivalent ofdocker run --env-file
); theenv_file
option specifies what env-vars to set on the container that’s created, but is not used in the compose file itself (and not used for substituting variables in the compose file before deploying the stack).Semantics aside, thanks for the update. When I say Docker, I don’t mean necessarily the daemon or engine, but the company that builds the tools. The genesis for the comment about there being little effort really stems from the fact that swarm-mode has been out for over a year and is still WAY behind where we were with a single-node using compose.
I can appreciate that they are different, but use the same file format, but that actually leads to more confusion, and potentially disappoint, when users discover that they have to trade features for using swarm. That and the fact that the DAB files are STILL being listed as experimental. Unfortunately, we made the decision to use swarm-mode in a big project, or I wouldn’t even care. Fortunately, we won’t make that mistake again.
[edit]
Doing this in a CI environment is a royal ass pain. Essentially, I ended up installing compose, sourcing the envvars, washing the compose file through (after pulling the images) and then spitting out a new compose file for use with
stack deploy
. (And I won’t even start in on how painful it is when:latest
doesn’t mean:latest
in swarm-mode, since this issue is specifically about variable interpolation.)Hello All, Today I tried to run
docker stack deploy
. Mydocker-compose.yml
file:And
.env
file in the same directory:After launch
docker stack deploy -c docker-compose.yml test
, I inspected container and got this:Seems that,
.env
provided in container, but not provided on host machine. It means, that I can use.env
file instead ofenvironment
section, but I can’t use.env
file with Variable Substitution. Docker version: v17.03I wrote a compose-spec (compose v2) compliant docker-cli plugin replacement of
docker stack deploy
calleddeployx
usingcompose-go
that also does environment variable interpolation and handles.env
files. My hope is this kind of functionality can be added todocker stack deploy
, but in the mean time, I hope this plugin solves this issue for some people!A work around in powershell to use on windows in order to parse the .env file before calling docker:
Greatly inspired by parsing .ini files: https://stackoverflow.com/questions/417798/ini-file-parsing-in-powershell
+1
If the environment variables are set,
docker slack deploy
should already interpolate themDocker never had this feature; docker compose had; docker compose and docker stack deploy share the file format but not nescessarily all behaviors of the software itself.
Compose file handling is all done client side, and used both for k8s and swarmkit, so nothing slowing down in this area, other than “there’s only so much we can do at any given time”
For those waiting for that feature; the upcoming release will have support for multiple compose files for
docker stack deploy
, so if you’re currently using that feature in docker compose: the upcoming docker release will support this as wellI would add that having docker-compose installed only to be able to process these variables can also be quite dangerous actually.
If anyone deploy the stack using docker-compose up -d by mistake instead of using docker stack deploy, it would most probably induce applications errors and file corruption.
+1 It would be quite convenient to read the .env in the first place as docker-compose does. Either by default or just pass the env file as parameter in docker stack command line.
The two already mentioned workarounds (find them also below) seem to work although a little bit ugly compared to the proposed ‘fix’.
echo “$(docker-compose -f stack.yml config 2>/dev/null)” | docker stack deploy -c- stack_name
env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy --compose-file docker-compose.yml [STACK_NAME]
“For other stuff, may I suggest having one compose file per deployed/deployable environment ? Most of the stuff that changes between different environments will be the available servers, different server organization, etc… and thus needing different values on the deploy key contents (placement rules, resources reservations, etc), making using a single file for everything a bit too complicated.”
@vovimayhem Sorry to be blunt, but that doesn’t make nearly as much sense as using a single compose file with variable substitution using an env_file. I’d prefer to use the env_file format as this also makes it much easier for me to provide stacks as a deliverable to my customers and train them to update a single ini-style vars files than to mess with a compose file (which I DON’T want).
This should help @C-Pro - you need to have
export ...
lines in your.env
file. Alternatively, you can doexport $(cat .env)
, which would work for most cases.This is my aproach until I found this thread:
deploy.sh
:(stack_name optional if previously defined in .env)
+1 @joao-fidalgo It definitely is.
I can’t believe this isn’t possible. We would like to keep a single stack file and be able to change deployment options using dynamic variables.
This would work but is ugly and a hack:
echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_name
Thanks, but any word on simply supporting variable substitution from a file?
[edit] This shouldn’t be an issue (but could be) as I’m using Ansible to perform the task with
become: yes
, but the user is still the same user who sources the environment vars.@ntwrkguru https://docs.docker.com/engine/swarm/configs/
I came across this issue when looking for a solution to my
.env
not being read in bydocker stack deploy
. I was a bit surprised to see it wasn’t supported (docs could be clarified), but want to add my support for.env
, like compose.My use case is that I use
docker stack deploy
in dev, test, staging environments and use environment variables for stack options to keep the yml file the same.Currently using one of the workarounds posted here but using a
.env
file would be the preferred route.Here is what we do, it works very well on Docker Swarm cluster.
Hope it helps.
In the docs, it’s still listed as a ‘technical preview’ but some of the talks at DockerCon gave the impression it was now more mainstream than that. They were (confusingly) calling it Compose v2, but that’s nothing to do with the version numbers in the docker-compose.yml file.
The basic idea was to rewrite docker-compose in Go and include it in the main CLI, partly for speed but partly so it always had access to the latest facilities in the engine/CLI.
There are still some differences, but I’ve been using it all day for the last couple of days on my Mac with no issues other than those I mentioned above.
More info in this talk, if it’s accessible: https://docker.events.cube365.net/dockercon-live/2021/content/Videos/WGpFvvKmhhwvY52va
Quentin
Out of interest. What do people currently do when in swarm mode, and they want to update their newly built docker image from, e.g. application:v1 to application:v2, same service (nothing else changed)?
This is the reason I came to this issue. That is why I am interested.
Currently in docker-compose, it is trivial to get automation to interact with source-control untracked file
. env
to update the image version, thendocker-compose up -d
Often I use the commit sha as a docker image version for ‘staging’ deploys (git tags used for actual releases after sufficient testing cycles), so it isn’t really possible to commit the new image version to source control.
Is it possible to update a docker secret (even though it isn’t really a secret) as a workaround? Is that what people do, or is there something else that is done.
I am asking for future visitors of this issue, so that they actually come away with a current best practice, since the functionality they were looking for doesn’t (yet?) exist.
+1
Nice @rnickle, but still “hacky” compared to Docker being able to do this the way it used to. It seems (and please Docker dudes correct me if I’m wrong) that there is very little effort going into swarm-mode since the announcement of K8s support, so I’m doubtful that any of these regressions will be addressed.
see How to keep Environment Variables when Using SUDO
A year later and we still have to hack this to work. As of 17.09.1,
docker stack deploy -f compose.yml
won’t even substitute using known shell vars.Any variables for tags will produce
invalid reference format
.Thanks @djmaze, but that’s ultimately a ridiculous thing to need to do when there’s inherent version tracking built in to every source control system. Also, thanks for the link; I commented there as well. I don’t see why Docker cares about the version other than the one that’s current. The only reason I could see for needed to version these is for rollback, but tons of things need to be tracked there as well anyway, so what’s a couple more? (says the guy that doesn’t have to write the code) 😃
@thaJeztah , indeed it does. I have a task in my playbook to source an environments file, but that’s missing the bigger point. This used to be possible with
compose
and is now not possible withstack
. IMO, that’s a regression. Also, in your example, you’re still passing an environment variable into the container. I can do that with theenv_files
today; the issue is parsing theenv_file
during thestack deploy -c docker-compose.yml
operation.This is especially painful since
stack
no longer supports multiple compose files, else one could simply use a secondary compose file per environment. To do it that way requires one to build the stack file from the compose files, introducing another step. So, either way you look at it, we went from a single-step process to a multi-step process to accomplish the same end result.Also, FWIW, the
configs
is really subpar in my experience for actual configs. I was envisioning (hoping) that I could have/application/config.conf
in source. Update that file, commit, push and CI would re-deploy the stack with the new config. That’s not possible without some hackery to change the file name or some other mechanism. Surely we can checksum the file, at a minimum, or scan for content changes and update based on the file itself? All in all, it just seems like we’r’e going backwards. Throw in the support for K8s now and it makes me wonder if swarm will just languish on the vine until it loses enough usage that it’s quietly dropped.Just a friendly reminder: There might be the possibility your’e trying to use dotenv files to store API keys, passwords & other stuff considered to be “sensitive” to put into the cluster. For these cases, you should be using Docker Secrets.
For other stuff, may I suggest having one compose file per deployed/deployable environment ? Most of the stuff that changes between different environments will be the available servers, different server organization, etc… and thus needing different values on the
deploy
key contents (placement
rules,resources
reservations, etc), making using a single file for everything a bit too complicated.I’ve just noticed this. I assumed/expected it to work in the same way it does for Compose, but is not the case for
docker deploy
.In my particular case, I’m was expecting to use the
.env
file to store sensitive data (passwords, API keys, etc) used in the services I’ll be creating in the stack:While this Compose file will be checked in on Git, the
.env
file would be ignored.I’ve followed the whole stuff/history of the *.dab vs compose files, and I feel you guys are trying to avoid something - or proposing a better solution - but I lost track of the whole discussion…
If anyone is looking for a powershell script to replace the environment variables in a docker-compose.yaml file, here your go:
You can even pass the name of the .env and docker-compose.yaml file (with -envFilePath and -dockerComposeFilePath)
For people who would like to supply a custom .env file like .env.prod you can use the following: (Combining @kinghuang and @vovimayhem answers)
env $(cat .env.prod | grep ^[A-Z] | xargs) docker-compose config | docker stack deploy -c - stackname
To do this with a local registry, don’t forget to initialize a local registry with a given port (f.e.5000) and tag your services in the docker-compose.yml file with:
image: 127.0.0.1:5000/<parent_folder>_<service_name>
Then build with docker-compose and push them to the registry as explained here: https://docs.docker.com/engine/swarm/stack-deploy/
It’s worth noting, BTW, that the new, non-hyphenated
docker compose
, while admirable in many ways, doesn’t quite give the same output asdocker-compose
when run with theconfig
command. (I noticed that variable substitution was slightly different, and the ‘version’ line was missing.)So, even though I’ve switched to
docker compose
for most other things, I’m sticking with the hyphen for this particular case.As per many I hit this issue and found this. A solution that has worked for me is as follows: Create .env (or any other file name) with your variables:
Create startmystack.sh script containing the stack command required:
Variable picked up using source from .env, exported and then are available for substitution in the compose file for Swarm.
I can confirm that env_file is used and working for deploy stack command, exactly as the docker compose does.
@kinghuang Only the root environment will not report an error.
Another similar problem I just ran in to is that even if you use env_file, the behavior is still not exactly the same.
I use env_file to load paths specified from the project root, but my compose file is in a different subdirectory. To launch with docker-compose, I just use --project-directory . -f path/to/docker-compose.yml
docker stack
does not allow me to specify the project-directory, causing all of my env_files to fail to load.Changing env_file to “…/…/path/to/envrc” does not work with docker-compose, as these files must be inside the project root dir
I’ve been messing with this for many hours and looks like doing some background script work (I’ll be using CI to do this) to create a DAB file from these various pieces. It would be nice to be have a docker tool that would do this… 😃 Maybe add a
--env-file version.env
added todocker-compose bundle
?In my use case, I want to use a
version.env
“manifest” to track and control the versions of containers/images that comprise a platform. My process looks like this:.env
file.env
file to populate the shell varsdocker-compose -f stack.yml config > docker-compose.yml
docker-compose pull
to register the image digestsdocker-compose bundle -o stack.version.dab
DAB fileAt this point, ideally I would be able to
docker deploy --host manager.swarm.com --bundle-file stack.version.dab --with-registry-auth --resolve-image always stack-name
, but I get that it’s not possible now. In this case, I would scp the DAB file to the manager and execute thedocker deploy
.Is this the workflow Docker had in mind @thaJeztah? Is there a better way?
[edit] This does not work since a DAB ignores
volume:
,network:
, anddeploy:
directives. I’ve taken to simply sourcing an env file to the shell, rebuilding a temp compose file, then deploying that.+1
Thanks, I opened https://github.com/docker/docker.github.io/issues/3654 to fix the docs
@realcbb Yes. But for using
.env
file variables inside container, you must remove their inenvironment
section. For example: docker-compose.yml.env
In container I got this:
But if I remove
FOO
fromenvironment
section indocker-compose.yml
, I got this:The design of
docker stack
deploy is a bit different fromdocker-compose
commands. I don’t think it makes sense to just read a.env
by default. Not even thedocker-compse.yml
is read by default, because in the future the default deploy source will likely be something else.You can always source an
.env
file yourself before runningstack deploy
.