Reputation: 32629
I'm building a container for a ruby app. My app's configuration is contained within environment variables (loaded inside the app with dotenv).
One of those configuration variables is the public ip of the app, which is used internally to make links. I need to add a dnsmasq entry pointing this ip to 127.0.0.1 inside the container, so it can fetch the app's links as if it were not containerized.
I'm therefore trying to set an ENV
in my Dockerfile which would pass an environment variable to the container.
I tried a few things.
ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`
Everything passes the "REQUEST_DOMAIN" string instead of the value of the environment variable though. Is there a way to pass environment variables values from the host machine to the container?
Upvotes: 405
Views: 526329
Reputation: 3076
When using build-arg
...
docker build --build-arg CODE_VERSION=1.2 Dockerfile
...consider that the variable is not available after FROM
:
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
An
ARG
declared before aFROM
is outside of a build stage, so it can’t be used in any instruction after aFROM
.
Generally ARG
s should be placed after FROM
if not required during FROM
:
FROM base:xy
ARG ABC=123
To use the default value of an
ARG
declared before the firstFROM
use anARG
instruction without a value inside of a build stage:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
Upvotes: 5
Reputation: 11
Correct me if I wrong. The question was about env variables - not about args. The question was How to send ENV var to container - it means that container can reference to that variable. So I think the answer should be the following:
docker run --name [container-name] -e "[variable-name]=[new-value]" [image-name]
Upvotes: 1
Reputation: 1771
You can directly pass env variables when container start :
docker run -e [your_variable_name = your_variable_value] [image to instanciate]
Example :
docker run --rm -e TARGET=192.168.1.9 ubuntu env
The output is :
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=36399469e519
TARGET=192.168.1.9
HOME=/root
The target variable was added to your env variables of the current container !
Upvotes: 2
Reputation: 1099
This is for those looking to pass env variable from docker-compose using .env
file to dockerfile during build and then pass those args as env variable to container.
Typical docker-compose file
services:
web:
build:
context: ./api
dockerfile: Dockerfile
args:
- SECRET_KEY=$SECRET_KEY
- DATABASE_URL=$DATABASE_URL
- AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
Pass the env variable present in .env
file to args in build command.
Typical .env
file
SECRET_KEY=blahblah
DATABASE_URL=dburl
Now when you run docker-compose up -d command, docker-compose file takes values from .env file then pass it to docker-compose file. Now Dockerfile of web containes all those varibales through args during build. Now typical dockerfile of web,
FROM python:3.6-alpine
ARG SECRET_KEY
ARG DATABASE_URL
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_BUCKET
ARG AWS_REGION
ARG CLOUDFRONT_DOMAIN
ENV CELERY_BROKER_URL redis://redis:6379/0
ENV CELERY_RESULT_BACKEND redis://redis:6379/0
ENV C_FORCE_ROOT true
ENV SECRET_KEY ${SECRET_KEY?secretkeynotset}
ENV DATABASE_URL ${DATABASE_URL?envdberror}
Now we recieved those secret_key and db url as arg in dokcerfile. Now let's use those in ENV
as ENV SECRET_KEY ${SECRET_KEY?secretkeynotset}
. Now even docker container has those variables in it's environment.
Remember not to use ARG $SECRET_KEY
(which I did). It should be ARG SECRET_KEY
Upvotes: 93
Reputation: 376
An alternative using envsubst
without losing the ability to use commands like COPY
or ADD
, and without using intermediate files would be to use Bash's Process Substitution:
docker build -f <(envsubst < Dockerfile) -t my-target .
Upvotes: 24
Reputation: 11541
You should use the ARG
directive in your Dockerfile which is meant for this purpose.
The
ARG
instruction defines a variable that users can pass at build-time to the builder with the docker build command using the--build-arg <varname>=<value>
flag.
So your Dockerfile will have this line:
ARG request_domain
or if you'd prefer a default value:
ARG request_domain=127.0.0.1
Now you can reference this variable inside your Dockerfile:
ENV request_domain=$request_domain
then you will build your container like so:
$ docker build --build-arg request_domain=mydomain Dockerfile
Note 1: Your image will not build if you have referenced an ARG
in your Dockerfile but excluded it in --build-arg
.
Note 2: If a user specifies a build argument that was not defined in the Dockerfile, the build outputs a warning:
[Warning] One or more build-args [foo] were not consumed.
Upvotes: 605
Reputation: 1548
If you just want to find and replace all environment variables ($ExampleEnvVar) in a Dockerfile then build it this would work:
envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -
Upvotes: 7
Reputation: 171
Load environment variables from a file you create at runtime.
export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF
... then in the Dockerfile
ADD build /build
RUN /build/test.sh
where test.sh loads MYVAR from env.sh
#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
Upvotes: 17
Reputation: 2429
So you can do:
cat Dockerfile | envsubst | docker build -t my-target -
Then have a Dockerfile with something like:
ENV MY_ENV_VAR $MY_ENV_VAR
I guess there might be a problem with some special characters, but this works for most cases at least.
Upvotes: 69