Docker Tip #47: Build Time vs Run Time ENV Variables
Docker allows you to set both build time and run time ENV variables and even lets you overwrite build time ENV vars at run time.
There may come a time where you’ll want to add an ENV
variable to your Docker
image, but you’ll want this value to be different depending on where you build
your image, but you don’t want to edit your Dockerfile
to change it.
You may also want to sometimes overwrite that value at run time (not build time).
Setting up a Docker image with a build argument and ENV variable:
FROM debian:stable-slim
ARG YOURAPP_ENV=production
ENV YOURAPP_ENV="${YOURAPP_ENV}"
YOURAPP_ENV
could be RAILS_ENV
, NODE_ENV
or whatever environment
variable you want to set at build time.
The ARG
and ENV
variable names don’t need to match, but it’s generally a
good idea to keep them the same for consistency. In this case, the ENV
variable
will default to whatever the ARG
is set to at build time (or “production” if
none is supplied).
A few outcomes when building and running the above Docker image:
# A typical build.
docker build -t yourapp .
docker run --rm yourapp env | grep YOURAPP_ENV
> YOURAPP_ENV=production
# Building it with a custom --build-arg value.
docker build -t yourapp --build-arg YOURAPP_ENV=staging .
docker run --rm yourapp env | grep YOURAPP_ENV
> YOURAPP_ENV=staging
# Overwriting the ENV's value at run time instead of build time.
docker run --rm -e YOURAPP_ENV=development yourapp env | grep YOURAPP_ENV
> YOURAPP_ENV=development
If you’re using Docker Compose instead, it supports both setting build arguments and also setting environment variables at run time, so this all works the same way.
A quick Docker Compose example that sets a build argument:
services:
yourapp:
build:
context: "."
args:
YOURAPP_ENV: "helloworld"
Now if you run docker-compose up --build
and took a look at the environment
variables in the container you would see YOURAPP_ENV=helloworld
.
You could even define that arg as a variable with ${YOURAPP_ENV:-helloworld}
and if you have it defined in a .env
file then Docker Compose will pick it up
automatically. If it’s not defined it’ll fall back to the default value of
helloworld
.
Also, if you set YOURAPP_ENV
as an environment variable in the
docker-compose.yml
file with the environment
property (or being loaded in
from a file with env_file
) it would overwrite the build argument just like it
did without Docker Compose. Feel free to try that out on your own!