Re-using variables in docker-compose yml - docker

There are two articles describing using environment variable but my use case is different.
I have docker-compose file where I have 3-7 containers. Depends on situation.
version: '2'
services:
db:
image: example/db
backend:
image: example/server
frontend:
image: example/gui
Now, in above example all my images will use latest version, but I would like to control which version to deploy, therefore I want to define some variable version and use it in all my images, something like:
version: '2'
variable version=1.0.1
services:
db:
image: example/db:$version
backend:
image: example/server:$version
frontend:
image: example/gui:$version
Second example is wrong, but it shows my need what I want to achieve

In the same directory as docker-compose.yml add an environment file named .env, then specify your environment variable.
After that, add variable into your docker-compose.yml
The ${..} represents a variable in .env

Docker-compose used Interpolation Syntax ${variable} for variables and you missed that in your file.
version: '2'
services:
db:
image: example/db:${version}
backend:
image: example/server:${version}
frontend:
image: example/gui:${version}
So just pass the version to your docker-compose command
version=1.13-alpine docker-compose up

Related

Dockerfile - use environment variable from env file

I have a docker compose setup where I want to use environment variables from env file in my dockerfile. I want to use these variables during the build time since I use this version number in concatenating the string in order to form a download URL.
Here I wrote part of the files I'm using just to keep the focus on the point of my question.
.env
MY_APP_VER=v1.2.3
docker-compose.yml
version: "2"
services:
my-app:
build: .
container_name: my_app
environment:
- my_app_version=$MY_APP_VER
Dockerfile
FROM scratch
ENV my_app_ver=$my_app_version
RUN echo $my_app_ver
I have checked various sources but without any success. I'm not sure if this is even possible or am I using the wrong syntax (should I use quotes or no e.g. "$my_app_ver" or curly brackets ${my_app_ver}).
For version 3.8 you can do it in the following way
version: '3.8'
services:
my-app:
build: .
ports:
- ${CONTAINER_PORT}:${PORT} # for example
env_file: .env
container_name: my-app-${NODE_ENV} # for example
environment:
MYSQL_DATABASE: ${DB_NAME} # for example
my_app_version: ${MY_APP_VER} # for your case
Find more information in documentation
Also, you can find more information about the usage of env variables in Dockerfile and docker-compose here
There is an option called env-file in docker-compose, that you can leverage: https://docs.docker.com/compose/environment-variables/#the-env_file-configuration-option
version: "3"
services:
my-app:
build: .
container_name: my_app
env_file:
- .env.dev
Be aware, that the .env file is loaded by default, if it is present in the current context. So you only have to use env_file, if it is named differently or is in a different folder.

Parametrize docker-compose image pull

I have a docker-compose yaml that looks like the following:
version: '3'
services:
my-service:
image: xxxx.dkr.ecr.eu-central-1.amazonaws.com/yyyy:latest
It pulls the latest image of a docker in ecr. I want to slightly change it to
version: '3'
services:
my-service:
image: xxxx.dkr.ecr.eu-central-1.amazonaws.com/yyyy:${tag}
that is, to be able to pass a tag parameter when I do the build. Is it possible to do this?
You can use a .env file in the same directory where your docker-compose.yaml is located or you pass it to the cli like tag=latest docker-compose up.
Example .env file:
tag=latest

Environment property not injected to volume mapping

I run docker-compose up in a parent directory and -f the docker-compose.yml in child folder. Does anyone know why this won't work? MY_VAR is evaluated to empty string
root-ui-e2e-ci:
environment:
MY_VAR: ./hello
env_file: ./.env
volumes:
- ${MY_VAR}:/app
I end up with this error
.: volume name is too short, names should be at least two alphanumeric
characters
The variable specified in environment & env_file not used for compose-file, it will directly pass to container.
For variable substitution in docker-compose.yaml, you could use next two solutions, and use docker-compose config to quick check the effect:
Solution 1:
Use the variable export in the same shell which run docker-compose:
docker-compose.yaml:
version: '3'
services:
root-ui-e2e-ci:
image: ubuntu
volumes:
- ${MY_VAR}:/app
Try Command:
$export MY_VAR=./hello
$docker-compose config
services:
root-ui-e2e-ci:
image: ubuntu
volumes:
- /home/shubuntu1/99/hello:/app:rw
version: '3.0'
Solution 2:
Use .env:
Set a .env file in the same folder of docker-compose.yaml:
.env:
MY_VAR=./hello
docker-compose.yaml:
version: '3'
services:
root-ui-e2e-ci:
image: ubuntu
volumes:
- ${MY_VAR}:/app
Try Command:
$unset MY_VAR
$docker-compose config
services:
root-ui-e2e-ci:
image: ubuntu
volumes:
- /home/shubuntu1/99/hello:/app:rw
version: '3.0'
depends on you comment that hello is a stringyou need to rewrite you docker-compose like this:
environment:
MY_VAR: hello
volumes:
- ../${MY_VAR}:/app

Docker-compose specify tags from env file

I have docker-compose.yml like below:
version: '2'
services:
micro-service:
image: some/micro-service:${SERVICE_VERSION}
env_file:
- ../all-variables/${PROFILE}/micro_service.env
ports:
- "8085:8085"
And I have two files : dev.env and stage.env where SERVICE_VERSION and PROFILE are described.
Is there any way to specify concrete file when running docker-compose up
By default docker-compose takes .env file from current dir.
Is there a way to override it or another workaround ?
As mentioned in the answer in the comments there is no way to do that as it is directly coded into the source code to use .env.
However, there a couple ways to get similar behaviour.
The first way works natively with docker-compose, which would be to use docker-compose override files.
So in your case you could have your base docker-compose.yml file like this:
version: '2'
services:
micro-service:
image: some/micro-service:1.0.0
ports:
- "8085:8085"
Then you can define a docker-compose-dev.yml file:
version: '2'
services:
micro-service:
image: some/micro-service:dev
env_file:
- ../all-variables/dev/micro_service.env
Then you can run the following command
$ docker-compose up -f docker-compose.yml -f docker-compose-dev.yml up
If you do this the values in docker-compose-dev.yml will override those in docker-compose.yml. So instead of using image some/micro-service:1.0.0 it will use the image defined in docker-compose-dev.yml.
The second way would be to use docker-app. Which is a new experimental utility from the Docker team.
Basically you will create a dockerapp file that would look like this:
version: 0.0.1
name: app
---
version: '2'
services:
micro-service:
image: some/micro-service:${SERVICE_VERSION}
env_file:
- ../all-variables/${PROFILE}/micro_service.env
ports:
- "8085:8085"
---
SERVICE_VERSION: latest
PROFILE: default
Then if you convert your .env files to .yml render the compose file with the correct variables using docker-app.
docker-app render -f dev.yml | docker-compose -f - up
Hopefully this is helpful, I am going through a similar issue when working with multiple environments with docker-compose.

Specify hostname of service container on CLI?

With docker-compose, I can specify the hostname for a service container.
docker-compose.yml:
version: "3"
services:
db:
image: library/mysql:latest
app:
build: .
hostname: my-hostname
Rather than define this in the compose file, can I pass it in as an option on the CLI, either during the docker-compose build or docker-compose up phase?
docker-compose supports environment variables. So you can pass it using that
version: "3"
services:
db:
image: library/mysql:latest
app:
build: .
hostname: ${APP_HOSTNAME}
Then use
APP_HOSTNAME=myapp docker-compose up
or
export APP_HOSTNAME=myapp
docker-compose up
Edit-1
If you want to use default values in environment that is also possible
It is possible to provide inline default values using typical shell syntax:
${VARIABLE:-default} will evaluate to default if VARIABLE is unset or empty in the environment.
${VARIABLE-default} will evaluate to default only if VARIABLE is unset in the environment
So you can updated your docker-compose to below and it will work in all terminals
version: "3"
services:
db:
image: library/mysql:latest
app:
build: .
hostname: ${APP_HOSTNAME:-myapp}

Resources