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
.envsupport. Thedocker stack deploycommand was originally built with Distributed Application Bundle files in mind (hence the--bundle-fileoption). DAB files were generated by Docker Compose with thedocker-compose bundlecommand..envand other Compose features would be handled bydocker-compose, before being passed todocker stack deploy. Direct support for Compose files indocker stack deploywas 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 configto 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
.envprocessing are fully applied.@whoan I’m using this as a workaround:
That way, variables don’t get stuck on the terminal window
The
.envsupport is quite useful in Compose, we used it in many of our compose files. It separates dynamic parts and static parts ofdocker-compose.ymlfile. With load.envby default, we can just provides different.envfile for different environments, and keeping thedocker-compose.ymland related scripts static.It’s not possible to use
env_fileorenvironmentindocker-compose.ymlto achieve the same envvars substitution result..envis the most easy way to do it.Otherwise, we have to prefix
exportin each line of.envfile and manuallysource .envevery time before loading thedocker-compose.yml, and the extra steps sometimes are prone to mistake.This is by design. The
.envsupport 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 stackcommands.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
secretsfeature be released:To summarize, for people like me, who have read this so far:
docker stack deploysupports “Variable Substitution” but you need to set the environment variables from the.envfile in some way. Several options have been explained above. One of the neatest workarounds is usingdocker-compose configas pre-processor. So you can create your stack withdocker stack deploy -c <(docker-compose config) STACK_NAME.env_fileparameter in thedocker-compose.ymlfile will set the environment variables in the created container and not on thedocker-compose.ymlfile itself (and hence it cannot be used as an alternative to “Variable Substitution”).Update:
I was corrected by @thaJeztah.
Just
. .envbefore callingdocker stack deploydoes not help, $variables are not substituted. Onlyenv .. xargstrick did help. It would be nice to have--env-file=FILEoption like indocker run.BEWARE of the
<(docker-compose -f CUSTOM-COMPOSE-FILENAME.yml configHACK!!! The output ofdocker-compose configanddocker-compose -f myfile.yml configis 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 deployIt will also work with
docker-compose upfor bash@andyfinch Alternatively:
or:
set -aadds the export attribute to every variable that gets created.set +arestores the default behavior.@akhildangore please don’t comment on issues with questions that are not directly related. The
docker stack deployfeature, 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
.envfiles were read by default like in Docker Compose and--env-file(short-e) would be added fordocker stack deployto be able to override environment variables and the defaults from the.envfile.docker stack deploycan 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-namePlease 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 configis what ties this together.Try this:
echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_nameIt 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/filenoti 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:
loadenvsenvfileand assign the first argument to the function to it; if there is no argument, use ‘.env’ insteadenvfilewith 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
sudoto run docker commands, you need to use-Eoption 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
.envfile - 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 deployto deploy a complete stack and you have the following requirements:If you can’t configure this with a
.envfile, you need to manually change thedocker-compose.ymlfile 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
.envfile, if one exists in the same directory asdocker-compose.ymlif 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.0error. (see https://github.com/docker/compose/issues/8950) This happens because nowconfigcommand trimmsversionfield.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
.envfile, 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 deployas it was duringcompose up.docker stack deploydoes support variable substitution, but does not evaluate the.envfile; in the example below,HELLO_VERSIONis set tolinux, and the service will use thehello-world:linuxtag (instead of the defaulthello-world:latest)The
env_fileserves a different purpose (and is the equivalent ofdocker run --env-file); theenv_fileoption 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:latestdoesn’t mean:latestin swarm-mode, since this issue is specifically about variable interpolation.)Hello All, Today I tried to run
docker stack deploy. Mydocker-compose.ymlfile:And
.envfile in the same directory:After launch
docker stack deploy -c docker-compose.yml test, I inspected container and got this:Seems that,
.envprovided in container, but not provided on host machine. It means, that I can use.envfile instead ofenvironmentsection, but I can’t use.envfile with Variable Substitution. Docker version: v17.03I wrote a compose-spec (compose v2) compliant docker-cli plugin replacement of
docker stack deploycalleddeployxusingcompose-gothat also does environment variable interpolation and handles.envfiles. 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 deployshould 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.envfile. 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_nameThanks, 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
.envnot 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 deployin 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
.envfile 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
. envto update the image version, thendocker-compose up -dOften 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.ymlwon’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
composeand 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_filestoday; the issue is parsing theenv_fileduring thestack deploy -c docker-compose.ymloperation.This is especially painful since
stackno 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
configsis really subpar in my experience for actual configs. I was envisioning (hoping) that I could have/application/config.confin 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
deploykey contents (placementrules,resourcesreservations, 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
.envfile 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
.envfile 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 - stacknameTo 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-composewhen run with theconfigcommand. (I noticed that variable substitution was slightly different, and the ‘version’ line was missing.)So, even though I’ve switched to
docker composefor 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 stackdoes 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.envadded 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:.envfile.envfile to populate the shell varsdocker-compose -f stack.yml config > docker-compose.ymldocker-compose pullto register the image digestsdocker-compose bundle -o stack.version.dabDAB 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
.envfile variables inside container, you must remove their inenvironmentsection. For example: docker-compose.yml.env
In container I got this:
But if I remove
FOOfromenvironmentsection indocker-compose.yml, I got this:The design of
docker stackdeploy is a bit different fromdocker-composecommands. I don’t think it makes sense to just read a.envby default. Not even thedocker-compse.ymlis read by default, because in the future the default deploy source will likely be something else.You can always source an
.envfile yourself before runningstack deploy.