Environment variables in Docker - docker

I am trying to set up our production environment in a docker image.
After spending some hours compiling software, I realized that I forgot to set the locale environment variables in the Dockerfile.
Is there a way to permanently commit environment variables to an image?
I only came across the dockerfile way of doing this and I don't want to rebuild from that and lose all the work already done.
Setting those variables in .bashrc is not working, as the docker run command seems to bypass those settings.

Is there a way to permanently commit environment variables to an image?
That is the directive ENV in Dockerfile.
ENV <key> <value>
ENV <key>=<value> ...
But since you don't want to rebuild the image (although you could add it at the end of the dockerfile, and benefit from the cache for most of the image build), you can still launch your containers with docker run -e "variable=value"

You can change environment variables during a "docker commit" operation to modify an existing image. See https://docs.docker.com/engine/reference/commandline/commit/ and this StackOverflow Q&A: Docker Commit Created Images and ENTRYPOINT - and reference the answer by sxc731. It is not clear to me how one sets multiple Env variables, but it might take a separate --change for each.
Here is an example of what I was just doing (bash shell):
docker run -it --entrypoint /bin/bash $origimghash
# make changes, leave running, then in another shell:
EP='ENTRYPOINT ["python","/tmp/deploy/deploy.py"]'
ENV='Env no_proxy "*.local, 169.254/16"'
docker commit "--change=$ENV" "--change=$EP" $runninghash me/myimg
docker inspect -f "{{ .Config.Env }}" $newhash

Related

How to use export command to set environment variable with docker exec?

I have a running docker container using an ancestor my_base_image. Now when the container is running, can I set an environment variable using export command with docker exec? if yes, how?
I tried using the following, but doesn't work
docker exec -i -t $(docker ps -q --filter ancestor=`my_base_image`) bash -c "export my_env_var=hey"
Basically I want to set my_env_var=hey as env variable inside docker container. I know this can be done in may ways using .env_file or env key docker-compose & ENV in Dockerfile. But I just want to know if it is possible using docker exec command
This is impossible. A process can never change the environment of any other process beyond itself, except that it can specify the initial environment of processes it starts itself. In this case, your docker exec shell isn’t launching the main container process, so it can’t change that process’s environment variables.
This is one of a number of changes that you will need to stop, delete, and recreate the container for. You should treat this as extremely routine container maintenance and plan to delete the container eventually. That means, for example, keeping any data that needs to be persisted outside the container, ideally in an external database but possibly in a mounted volume.

How do I pass in configuration settings to a docker image for local development?

I'm working on a dotnet core docker container (not aspnet), I'd like to specify configuration options for it through appsettings.json. These values will eventually be filled in through environment variables in kubernetes.
However, for local development, how do we easily pass in these settings without storing them in the container?
You can map local volumes to docker -v local_path:container_path.
If you gonna use kubernetes you can use ConfigMap as well.
You can pass env variables while running the container with -e flag of the command docker run.
With this method, you’ll have to pass each variable in the command line. For example, docker run -e VAR1=value1 -e VAR2=value2
If this gets cumbersome, you can write these values to an env file and use this file like so, docker run --env-file=filename
For reference, you can check out the official docs.

How to pass a lot of bamboo variables to a docker container?

I have the Docker configuration task and I need to execute in docker container a bash script which uses Bamboo variables.
Is there a way to pass all Bamboo variables to docker container?
I have lots of Bamboo plans with quite a few different variables in them so putting all variables in container environment variables is not an option.
Of course, I can dump them into file in one task and parse the variables from file in docker task, but I was hoping to find an easier solution.
Thanks!
What version of Bamboo are you using?
There are a problem with bamboo variables is docker containers in some versions of Bamboo, but was fixed in Bamboo 6.1.0:
Unable to use variables in Container name field in Run docker task
Workaround:
Create a Script Task that runs before the Docker Task.
Run commands like
echo "export sourcepath=$ini_source_path" > scriptname.sh
chmod +x scriptname.sh
The Docker Task will be map the ${bamboo.working.directory} to the Docker \data volume.
So the just created scriptname.sh script is available in the Docker container.The script will be executed, and will set the variable correctly.
More info in this post:
How to send bamboo variables from Bamboo script to docker container?
I think the only way is what you mention already - dump the env variables to file in dedicated task earlier in the flow. Say, you do it like so:
#!/bin/bash
env | grep ^bamboo_ > my_env_file
Note the strict regex preventing dumping variables such as PATH.
Then in the docker task, in "Additional arguments" add the following
--env-file=my_env_file
You can use the env_file option using compose:
web:
env_file:
- your-variables.env
or use docker run --env-file=your-variables.env ....
The .env file is a simple key value text file:
# my env file
BAMBOO_ENV=development

Docker environmental variables from a file

I am trying to use one Dockerfile for both my production and development. The only difference between the production and development are the environment variables I set. Therefore I would like someway import the environment variables from a file. Before using Docker I would simply do the following
. ./setvars
./main.py
However if change ./main.py with the Docker equivalent
. ./setvars
docker run .... ./main.py
then the variables will be on the host and not accessible from the Docker instance. Of course a quick and dirty hack would be to make a file with
#!/bin/bash
. ./setvars
./main.py
and run that in the instance. That would however be really annoying, since I got lots of scripts I would like to run (with the same environment variables), and would then have to create a extra script for everyone of those.
Are there any other solution to get my environment variables inside docker without using a different Dockerfile and the method I described above?
Your best options is to use either the -e flag, or the --env-file of the docker run command.
The -e flag allows you to specify key/value pairs of env variable,
for example:
docker run -e ENVIRONMENT=PROD
You can use several time the -e flag to define multiple env
variables. For example, the docker registry itself is configurable
with -e flags, see:
https://docs.docker.com/registry/deploying/#running-a-domain-registry
The --env-file allow you to specify a file. But each line of the file
must be of type VAR=VAL
Full documentation:
https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables-e-env-env-file

Can a variable be used in docker FROM?

I am wondering if a env variable can be used in a docker from? Reason for this is to control the tagging. For example, say I have this line in my Dockerfile:
FROM myApp
What I want is this:
FROM myApp:${VERSION}
This way I can say docker build . myApp --build-arg VERSION=9
The process to build docker images for this app is the same. I don't want to have Dockerfiles that are almost identical just to use a different base image.If I want to build version 9, it should use version 9 of the base image.
Quoting this link
:
This is now possible if anyone comes here looking for answers: https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
FROM instructions support variables that are declared by any ARG instructions that occur before the first FROM.
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
For at least this docker version this is feasible
docker --version
docker version 18.09.8, build bfed4f5
It requires a preset variable in Dockerfile e.g.
ARG TAG=latest
FROM traefik:${TAG}
Then you can override this preset with the following
docker build --build-arg "TAG=2.2.8" -t my-app:$TAG
The version number will not show up during build. if you want to test if it works, reference a non-existing version - it will fail with: manifest my-app:version not found.
You could simply generate your Dockerfile from a template. Put
something like this in a Makefile:
MYTAG=latest
.PHONY: Dockerfile
Dockerfile: Dockerfile.in
sed 's/MYTAG/$(MYTAG)/' $< > $# || rm -f $#
Then you can run:
make MYTAG=8; docker build -t my-app-8 .
This would only make sense if you are frequently building images that
require a different tag in the FROM line.
It is not possible.
Although, you can use a variable tag like from myApp:latest and overwrite the latest tag when you're creating a new version.
Build your container programatically using buildah (It can take Dockerfile too).
So for your use-case:
VERSION=v0.1.0
myCon=$(buildah from myApp:${VERSION})
buildah config --cmd "sleep 1d" $myCon
buildah commit $myCon $USER/sleeping1d
You can obviously script it, save and invoke it, and one more advantage is
buildah doesn't need docker daemon running, which is great for CI. Also it's an open-source project, check out the project page.
BTW I saw this issue lately which is exactly what you want - https://github.com/projectatomic/buildah/issues/581
Unfortunately it's not possible to do that. The first line of your Dockerfile must be a FROM directive, and so that precludes the use of the ARG directive. There is a good answer there from larsks about generating a Dockerfile, but I'd also like to suggest merely creating different Dockerfiles and then specifying a particular one in your docker build command using the -f switch:
docker build -t codemiester/app:latest -f ./Dockerfile.apache2.ubuntu

Resources