Reputation: 562
I am trying to use the same docker-compose.yml and .env files for both docker-compose and swarm. The variables from the .env file should get parsed, via sed, into a config file by running a run.sh script at boot. This setup works fine when using the docker-compose up
command, but they're not getting passed when I use the docker stack deploy
command.
How can I pass the variables into the container so that the run.sh script will parse them at boot?
Upvotes: 6
Views: 8574
Reputation: 7802
In 2024 due to ongoing Compose and Swarm development the other answers age, unfortunately. If you need the variables interpolation in your Swarm compose files here is what works to date.
Summary: docker compose -f file.yml config...
does not produce the compose file required for Swarm. Neither docker stack deploy --compose-file...
would interpolate env_file
variables. Use docker stack config
(docs) first instead, then forward its outcome to docker stack deploy...
.
Here is the example.
# file: a-service.swarm.yml
services:
a-service:
image: "image:tag"
env_file:
# Provide container (!) with environment variables at runtime
# Will not provide variables interpolation at Swarm build time with
# `docker stack deploy --compose-file a-service.swarm.yml my-stack`
- ./some.env
environment:
# This is required to override the uninterpolated 'env_file' variables
# that require interpolation
- REQUIRES_INTERPOLATION=${A_VALUE:-default_constant_value}
# file: some.env
A_VALUE=a-value
DOES_NOT_REQUIRE_INTERPOLATION=another-value
# A_VALUE not going to be interpolated with `env_file`
# But it is with `docker stack config...`
REQUIRES_INTERPOLATION=${A_VALUE:-default_constant_value}
docker stack config --compose-file a-service.swarm.yml > processed.swarm.yml
docker stack deploy --compose-file processed.swarm.yml my-service
Look up the interpolated values in processed.swarm.yml
when you debug the thing.
Upvotes: 1
Reputation: 263469
Loading the .env
file is a feature of docker-compose that is not yet supported in docker stack
commands. You can manually load the contents of this file in your shell before performing the deploy:
set -a; . ./.env; set +a
docker stack deploy -c docker-compose.yml stack_name
Other options include using docker-compose to pre process the compose file:
docker compose config >docker-compose.processed.yml
Or you could use envsubst to replace the variables to make a compose file with the variables already expanded:
set -a; . ./.env; set +a
envsubst <docker-compose.yml >docker-compose.processed.yml
Note that the .env
file is different from an env_file
section of a compose file. The .env
file is used to expand variables in the compose file itself. The env_file
declaration for a service injects environment variables into the container.
Upvotes: 12
Reputation: 844
As mentioned the native env_file
is limited to docker compose BUT there proper way to do it in swarm is to user docker stack config
say we have a .env file
foo=bar
and a compose file
version: "3.9"
services:
myservice:
env_file:
- .env
Then calling config yields the following
❯ docker stack config -c docker-compose.yml
version: "3.9"
services:
myservice:
environment:
foo: "bar"
putting it together with deploy we get
docker stack config -c docker-compose.yml | docker stack deploy -c - mystack
docker stack deploy -c <(docker stack config -c docker-compose.yml mystack) mystack
If you want to have a variable docker-compose.yml where you need to interpolate the docker-compose with variables from the .env file you can do this crazy hack
export $(grep -v '^#' .env-test | xargs) && docker stack config -c docker-test.yml
the compose file:
---
version: "3.9"
services:
myservice:
image: ${THE_IMAGE_NAME}
env_file: .env
the .env file:
a=1
THE_IMAGE_NAME=owner/image
the output:
❯ export $(grep -v '^#' .env | xargs) && docker stack config -c docker-compose.yml
version: "3.9"
services:
myservice:
environment:
THE_IMAGE_NAME: owner/image
a: "1"
env_file:
- .env
image: owner/image
Upvotes: 5
Reputation: 10720
To pass shell environment variables through to containers use env_file
syntax:
web:
env_file:
- web-variables.env
As docs state:
You can pass multiple environment variables from an external file through to a service’s containers with the ‘env_file’ option
However, using .env
as external filename may cause unexpected results and is semantically problematic.
Placing .env
in the folder where the docker-compose
command serves different purpose:
The environment variables you define here are used for variable substitution in your Compose file
You can set default values for environment variables using a .env file, which Compose automatically looks for
So if compose file contains:
db:
image: "postgres:${POSTGRES_VERSION}"
You .env
would contain:
POSTGRES_VERSION=4.0
This feature indeed works only in compose:
The .env file feature only works when you use the docker-compose up command and does not work with docker stack deploy
Upvotes: 1
Reputation: 562
Actually I found the best/easiest way is to just add this argument to the docker-compose.yml file:
env_file:
- .env
Upvotes: -3