Docker variables scope - docker

I want to know where can I see the variables I have defined. For example, I have three files:
.env
BLA=1
docker-compose.xml
IS_ONE=${BLA}
Dockerfile
RUN echo "$BLA" >> file.txt
I want to know the relation, for example:
Do I need the variable defined in all files? or there a relation like
docker-compose.xml can only see .evn variables?
Dockerfile can only see docker-compose.xml variables?
And, where do I need to declare a variable to use in a bash script automatically triggered in Dockerfile (if it's possible), or use later in the console of the container.

Lots of examples here: https://docs.docker.com/compose/environment-variables/
If you need to customize docker-compose itself then .env file is used.
For example, I want to include build id in my container name, my .env file would have
BUILD_ID=20
and docker-compose.yml would have
containername: "foo-${BUILD_ID}"
If I want to pass environment vars into container when it runs, I use
environment:
- FOO_VAR=bar
If I want to pass in multiple environment vars into container,
docker-compose.yml would have
env_file: my_container_env
is the easy way if the values of the FOO_VAR are going to be dynamically generated.
Whether to use set env values in docker-compose directly or use file depends on:
Are the values dynamic? If yes, use file and populate correct values
in the file with some script (like jenkins could set my BUILD_ID in
my .env file)
Are they 'secret'? If yes, use file and don't checkin the .env or my_container_env file into the repo - you have to manage those files
separately

Related

going from .env to environment variables

So I have been tasked with taking an existing dockerized version of a service, and creating docker images from this repository.
Creating the images is not the problem however, since the build command starts it up no problem. The issue is that this dockerfile copies an .env file during build, that holds variables that must be customizable after the build process is done (expected db and other endpoint info).
Is there some way to set that file to automatically be changed to reflect the environmental variables used in the docker run command? (I do want to note, that the docker image does copy the .env file into the working directory, it is not docker-compose reading that .env file)
I am sure that there has to be an easy way to do this, but all the tutorials I am pulling up just show you how to declare these variables, not how to get the files in docker to use them! Most of the code being run is javascript, and uses npm and yarn if that makes any difference...
docker does not provide any way to update files from environment variables on container start. But I don't think this is what you need anyway:
As I understand a .env file with default values is copied into the image at build time and you want to be able to change some of the values at runtime via container environment variables?
Usually such an .env file is read by the application and complemented by any variables set in the environment, i.e. you can override values from the file with environment variables. For javascript projects dotenv is a popular module to do this.
So to override say an API_ENDPOINT variable specified in .env you simply need to pass an environment variable with the same name and desired value to the container:
docker run -e API_ENDPOINT=/other/endpoint ...
If for some reason your applications do not work according to this convention and you actually need to change the values in the .env file you will need to write a custom script that updates/generates .env from the values of passed environment variables and use this script as ENTRYPOINT

Get environment variable from Dockerfile or docker-compose.yml

I tried to get the variable in docker-compose.yml like ${NODE_ENV} but doesn't work.
Also I don't want to send any param on my commands. I have defined already an environment variable on my system and I'd like to take that one from either one of these 2 files.
the solution was running export NODE_ENV=development again. I was losing this env var every time I was closing the terminal

How to Use Environment Variables in a .env file to fill out other environment variable in the same .env file

I am using a base.env as an env_file for several of my docker services.In this base.env I have several parts of the environment variable that repeat throughout the file. For example, port and ip are the same for three different environment variables.
I would like to specify these in an environment variable and reuse those variables to fill out the other environment variables.
Here is base.env:
### Kafka
# kafka's port is 9092 by default in the docker-compose file
KAFKA_PORT_NUMBER=9092
KAFKA_TOPIC=some-topic
KAFKA_IP=kafka
KAFKA_CONN: //$KAFKA_IP:$KAFKA_PORT_NUMBER/$KAFKA_TOPIC
# kafka topic that is to be created. Note that ':1:3' should remain the same.
KAFKA_CREATE_TOPICS=$KAFKA_TOPIC:1:3
# the url for connecting to kafka
KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://$KAFKA_IP:$KAFKA_PORT_NUMBER
I have tried writing
KAFKA_CONN: //$${KAFKA_IP}:$${KAFKA_PORT_NUMBER}/$${KAFKA_TOPIC}
in the environment section of the appropriate service in the docker-compose.yml, but this gets interpreted as a literal string in the container.
Is there a way to do what I want in the base.env file?
Thank you for your help!
You can actually do it like this (at least in vlucas/dotenv package (php), not sure about others, please check it yourself)
MAIL_NAME=${MAIL_FROM}
Read more about it here
There is no way to do this in an env_file since it is not run as a bash command. This means that the variable is not created and then concatenated into the next variable it appears in. The values are just read in as they are in the env_file.
I used $ in Node.js and React.js , and both worked
POSTGRES_PORT=5432
DATABASE_URL="postgresql://root#localhost:${POSTGRES_PORT}/dbname"
and in react
REACT_APP_DOMAIN=domain.com
#API Configurations
REACT_APP_API_DOMAIN=$REACT_APP_DOMAIN
I know that I am a little late to the party, but I had the same question and I found a way to do it. There is a package called env-cmd, which allows you to use a .js file as an .env file. The file simply needs to export an object with the keys being your environment variable names and the values being, well, the values. This now allows you to run javascript before the environment variables are exported and thus use environment variables to set others.
I temporarly managed to deal with this where I create a script to replace env file vars from another env file vars like so:
.env.baseurl:
BASEURL1=http://127.0.0.1
BASEURL2=http://192.168.1.10
.env.uris.default:
URI1=${BASEURL1}/uri1
URI2=${BASEURL2}/uri2
URI3=${BASEURL2}/uri3
convert-env.sh:
#!/bin/bash
# To allow using sed correctly from same file multiple times
cp ./.env.uris.default ./.env.uris
# Go through each variable in .env.baseurl and store them as key value
for VAR in $(cat ./.env.baseurl); do
key=$(echo $VAR | cut -d "=" -f1)
value=$(echo $VAR | cut -d "=" -f2)
# Replace env vars by values in ./.env.uris
sed -i "s/\${$key}/$value/g" ./.env.uris
done
then you can run docker run command to start the container and load it with your env vars (from .env.baseurl to .env.uris) :
docker run -d --env-file "./.env.uris" <image>
This is not the best solution but helped me for now.
Using Nextjs, in the .env.local file I have the following variables:
NEXT_PUBLIC_BASE_URL = http://localhost:5000
NEXT_PUBLIC_API_USERS_URL_REGISTER = ${NEXT_PUBLIC_BASE_URL}/api/users/register
it works well, I used the variable NEXT_PUBLIC_BASE_URL in the variable NEXT_PUBLIC_API_USERS_URL_REGISTER.
There is a simple way to do this you will just need to run:
env >>/root/.bashrc && source /root/.bashrc
this will append all environment variables inside /root/.bashrc then convert those if they have not been converted while passing the env-file
you can use something like this ${yourVar}
KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://${KAFKA_IP}:${$KAFKA_PORT_NUMBER}
I test this on PHP / Laravel .env it's working fine

How can I set multiple env variables pointing to the same value on docker?

I have several containers that I run together with docker-compose.
One of them, is mysql, which requires some variables to be set. I have those in a .env file:
MYSQL_USER='my_user'
MYSQL_PASSWORD='my_password'
MYSQL_ROOT_PASSWORD='supersecretpassword'
MYSQL_DATABASE='my_database'
And I am able to start the mysql container successfully.
The problem comes when I want to use another service for db migrations, which require the following variables set in the .env file:
SERVICE_DBUSER='my_user'
SERVICE_DBPASSWORD='my_password'
SERVICE_DBNAME='my_database'
And what I would like to write (this doesn't work), to avoid repetition, is something like:
SERVICE_DBUSER="$MYSQL_USER"
SERVICE_DBPASSWORD="$MYSQL_PASSWORD"
SERVICE_DBNAME="$MYSQL_DATABASE"
But docker doesn't recognize that and doesn't perform the substitution. In the docker docs, it also states that expects each line in an env file to be in VAR=VAL format.
My question is, is it possible to avoid the repetition?
Many thanks.
Compose will substitute environment variables into the YAML compose file when you reference them with $VARIABLE or ${VARIABLE}.
You can still use the .env file to set a default environment. But when you want to reference a variable, put it in the environment: section of the compose yaml:
environment:
SERVICE_DBUSER: "${MYSQL_USER}"
SERVICE_DBPASSWORD: "${MYSQL_PASSWORD}"
SERVICE_DBNAME: "${MYSQL_DATABASE}"
Then if you set, or source an alternate environment when running docker-compose you will get the new values substituted in.
$ MYSQL_USER="other" MYSQL_PASSWORD="opass" docker-compose start

Get or set env variable in docker-compose.yml file

I have got a docker-compose.yml file and there I define:
extra_hosts:
- "localhost:${MY_MACHINE_IP}"
It works if I define MY_MACHINE_IP as environment var earlier.
What I want to achieve is to perform action like:
extra_hosts:
- "localhost:<get MY_MACHINE_IP from env if it exists, if not set MY_MACHINE_IP env variable with value <docker-machine-ip>>"
In other words: I want to define it in extra_hosts section, if MY_MACHINE_IP is already specified, get it, if not - set this env. variable with value = my docker machine ip.
Is it possible?
Yes in according to docker documentation
docker-compose run SERVICE env
So i think the variables are not global as you may think. You have to pass them as parameters.
Read this.
You can use the package ruamel.dcw for that (dcw for Docker Compose Wrapper, disclaimer: I am the author of that package). It allows you to create a section with key user-data in your docker-compose.yaml file, which is stripped out before handing the file to the normal docker-compose. That section can look like:
user-data:
author: Your Name <your-name#youremail.com>
description: container for postfix/submission
env-defaults:
PORT: 587 # override during development
NAME: submission
DOCKER_BASE: /data0/DATA
and then you can use {PORT}, {NAME} and {DOCKER_BASE} in the rest of the file, with the option of overriding these default values with environment variables.
The utility also write out a file .dcw_env_vars.inc which you can copy into your container and source to get the appropriate values into scripts you RUN from within the Dockerfile

Resources