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!