docker compose refer variable substitution from alias - docker

I want to setup few services that will be using a common env var with slight changes. I was thinking if we can extract the common part of the env var into another var and refer it as an alias.
For eg., if i need to inject "FOO: FOO_1" in service foo-1 and likewise for several such services - foo-2, foo-3, etc.
I tried with something like below:
x-common-env-var: &common-foo
COMMON_FOO: FOO
services:
foo-1:
environment:
<<: *common-foo
FOO: "${COMMON_FOO}_1"
foo-2:
environment:
<<: *common-foo
FOO: "${COMMON_FOO}_2"
But this does not resolve the COMMON_FOO, all I get in the service is _1.
Is it possible to achieve this?
I know we could use the .env file or pass env vars to docker compose at runtime. But I am looking at a solution to implement inside the docker-compose.yaml file itself.

Related

Passing env variables from one service to another inside docker-compose.yml

Is there a way to pass environment variables from one service to the other inside docker-compose.yml ?
services:
testService:
environment:
TEST_KEY: 1234
testServiceTests:
environment:
TEST_KEY: I want to pull in the value 1234 here from service1
No.
However, there's an alternative. You may provide environment variables to all the services within the Docker Compose file by exposing them either from your shell, when you run the Compose or by using a special .env file, See documentation.
Using this approach, you would have a global (for the Compose) environment variable, say GLOBAL_TEST_KEY (it needn't have a different name) and you would be able to share this across multiple services:
services:
testService:
environment:
TEST_KEY: ${GLOBAL_TEST_KEY}
testServiceTests:
environment:
TEST_KEY: ${GLOBAL_TEST_KEY}
And then: docker-compose run -e GLOBAL_TEST_KEY="Some value" ....
Or, create a file called .env alongside docker-compose.yaml and, in .env:
GLOBAL_TEST_KEY="Some value"
And then: docker-compose run ...
NOTE No need to reference .env as it's included by default

In my docker-compose file, how can I set two env vars to the same thing without hard-coding the string twice?

I'm trying to construct a Docker container in which I have two environment variables set to the same thing. I have
version: "3.2"
services:
sql-server-db:
image: mcr.microsoft.com/mssql/server:latest
ports:
- 3900:1433
env_file: ./tests/.test_env
...
command: /bin/bash /my-app/my-script.sh
and then in my tests/.test_env file I have
MY_DB_PASSWORD=reallylongpassword
SA_PASSWORD=${MY_DB_PASSWORD}
I would like to set the "MY_DB_PASSWORD" and "SA_PASSWORD" env vars to the same thing, however, the above doesn't do it, because "SA_PASSWORD" seems to be set to the literal string "${MY_DB_PASSWORD}". How do I set my two variables to the same thing without hard-coding the "reallylongpassword" string twice?
This is not possible using env file, simply do in your script like this. This way is more flexible as it will take the value if not set.
SA_PASSWORD="${SA_PASSWORD:-$MY_DB_PASSWORD}"
If you are worry about password security, you should use docker secret but you need to run in Swarm mode.
Here is the dockerfile used by the image. You can define your own CMD to override the behavior and take your env or use the trick to take default value.
CMD .\start -sa_password $env:sa_password -ACCEPT_EULA $env:ACCEPT_EULA -attach_dbs \"$env:attach_dbs\" -Verbose
//using you MY_DB_PASSWORD instead of SA_PASSWORD
CMD .\start -sa_password $env:my_db_password -ACCEPT_EULA $env:ACCEPT_EULA -attach_dbs \"$env:attach_dbs\" -Verbose

Docker-compose: Replacement for the extends keyword

From the docker docs:
Docker Compose’s extends keyword enables sharing of common
configurations among different files, or even different projects
entirely. Extending services is useful if you have several services
that reuse a common set of configuration options. Using extends you
can define a common set of service options in one place and refer to
it from anywhere.
For some reason this feature was removed in version 3.
Found also this thread, but it is inactive for 2 years.
I'm trying to find a replacement for this feature in the newer versions.
Would like to hear if somebody found a replacement for extends.
Thanks.
There are 2 ways to achieve what you need, you can decide to use one of them or both at the same time as they work slightly differently:
Multiple compose files
You can specify multiple compose files when running a docker compose command, you could for instance set up your project with:
docker-compose -f config1.yml -f config2.yml up
You could also use an environment variable to specify your files:
COMPOSE_FILE=config1.yml:config2.yml docker-compose up
What happens is that docker compose creates a single config merging what you defined in each of them.
Here the documentation showing how to merge multiple compose files.
You can also generate your final config file running the config command.
YAML Anchors
Since docker compose files are basically YAML files, you can take advantage of YAML Anchors to define a block of properties and reuse them in multiple parts of your config.
For example:
version: '3'
common: &common
image: "myrepo/myimage"
restart: "unless-stopped"
volumes:
- "volume:/mnt/myvolume"
services:
service1:
<<: *common
ports:
- "5000:5000"
service2:
<<: *common
environment:
- MYENV: value

How to pass environment variables to docker-compose's applications

I want to pass environment variables that is readable by applications spin up by docker-compose up.
What is the proper way of using docker-compose up with varying configuration settings?
I don't want to use .env & environment: config as the environment variables are changing frequently & it is insecure to save tokens in a file.
docker-compose run -e does work a bit, but loses many.
It does not map the ports that defined in docker-compose.yml services.
Also multiple services are defined in docker-compose.yml and I don't want to use depends_on just because docker-compose up doesn't work.
Let's say I define service in docker-compose.yml
service-a:
build:
context: .
dockerfile: DockerfileA
command: node serviceA.js
In my serviceA.js, I simply use the environment variable:
console.log("This is ", process.env.KEY, "running in service A");
When I run docker-compose run -e KEY=DockerComposeRun service-a
I do get the environment variable KEY read by serviceA.js
This is DockerComposeRun running in service A
However I could only get one single service running.
I could have use environment: in docker-compose.yml
environment:
- KEY=DockerComposeUp
But in my use case, each docker compose would have different environment variable values, meaning I would need to edit the file each time before I do docker-compose.
Also, not only single service would use the same environment variable, .env even done a better job, but it is not desired.
There doesn't seem to be a way to do the same for docker-compose up
I have tried KEY=DockerComposeUp docker-compose up,
but what I get is undefined .
Export doesn't work for me as well, it seems they are all about using environment variable for docker-compose.yml instead of for the applications in container
To safely pass sensitive configuration data to your containers you can use Docker secrets. Everything passed through Secrets is encrypted.
You can create and manage secrets using the commands below:
docker secret create
docker secret inspect
docker secret ls
docker secret rm
And use them in your docker-compose file, either referring to existing secrets (external) or use a file:
secrets:
my_first_secret:
file: ./secret_data
my_second_secret:
external: true
You can use environment like this:
service-a:
build:
context: .
dockerfile: DockerfileA
command: node serviceA.js
environment:
KEY=DockerComposeRun
Refer at: https://docs.docker.com/compose/environment-variables/

Can you add ENV VAR to docker compose up command

I need to define an env var in docker compose (v2).
Now I just have something like:
environment:
- SERVERNAME=192.168.xx.xx
But I don't really like this approach. People need to modifiy the compose file. Is there way that I can do this more dynamic. Something like:
docker-compose up --env SERVERNAME=192.168.xx.xx
What is the best approach to do this?
I think it's not possible but the most close solution can be pass it in a env file
From de docker docs:
You can pass multiple environment variables from an external file through to a service’s containers with the ‘env_file’ option.
So you can create a env file with the variable, for example server.env, and reference it in the docker-composer.yml
env_file:
- server.env
Or you can create a .env file in the folder
$ cat .env
SERVERNAME=192.168.xx.xx
And change your config with:
environment:
- SERVERNAME=${SERVERNAME}
You can do it with -e "SERVERNAME=192.168.1.1" -e "SOMETHING=bla" syntax.
Or use something like Hashicorp's Vault.

Resources