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.

Dynamically configure Docker Image 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 the ARG values to the application code
  • Pass defined ARG at the docker build with --build-args flag
  • --build-arg can map the ARG 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.