Dynamically configure Docker Image builds
Docker builds can not receive environment variables in the same way Container execution can. Let's see how you can pass values to adjust builds.
Containers are the best way to deliver your software as you are shipping the whole system with needed dependencies.
But building these Images can be a hassle when you wanna build them for specific purposes.
You might need some dynamic values while building the Image so that you can generate the most optimal package at the build time; not while executing them.
But, there is no way to pass environment variables to the docker build
similar to the way we execute those images:
# build the image with the tag 'msql'
docker build -e NODE_ENV=production -t msql .
# let's run the image with the above-built tag
docker run -d msql -e NODE_ENV=production
In the above example, -e
in the build
command has no effect and will only assume the unassigned/default value case; on the contrary to run
So how can we pass the dynamic values to the docker build
command?
ARG and ENV
ARG
and ENV
keywords for Dockerfile
are here to the rescue.
But as we discussed above, ENV
has no effect from outside, so why are we using it? To propagate the values downstream which gain by ARG
keyword.
How does ARG
keyword work? Let's take a look at an example Dockerfile
:
FROM alpine:3.14
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main/ \
nodejs-current \
bash \
npm
ARG PORT
ENV PORT ${PORT:-3000}
WORKDIR app
COPY . .
RUN npm ci --prod
ENTRYPOINT [ "node", "index.js" ]
In the above Dockerfile
, we are using ARG PORT
. This means that we are allowing the build command to accept the PORT
argument
We can execute the following to pass the default PORT
at the build time:
docker build --build-args PORT=5000 -t mynode-app .
One big thing to keep in mind is that the ARG names are case sensitive, and hence should be used carefully.
Though, as they are case sensitive, they can be used to pick the values from the Environment of execution of the build command.
For example, we can define the PORT as an environment variable. And now, we don't need to capture the value from the environment, it is automatically mapped by Docker.
export PORT=50001
echo $PORT
# 50001
docker build --build-args PORT -t mynode-app .
So that's how we can customize the builds with ARG
and ENV
.
For the majority of applications, you might not need this much customisation of build images.
This way of customisation becomes highly useful in places where you are working with a lot of automation
Conclusion
- Use
ARG
to define passable values - Use
ENV
to propagate theARG
values to the application code - Pass defined
ARG
at thedocker build
with--build-args
flag --build-arg
can map theARG
name with environment variables
Let us know how and for what are you customising your Docker images through comments ? or on Twitter at @heypankaj_ and/or @time2hack
If you find this article helpful, please share it with others ?
Subscribe to the blog to receive new posts right to your inbox.