Managing Docker Build Time Secrets

image credit: xenonstack.com

While creating a docker image, we might need to use secrets for various purposes like:

  • pulling private packages(npm, gradle etc.)
  • git clone or any git actions
  • get private object storage files
  • ssh/rsync

There mostly, there are two ways for using secrets:

  • environment variable
  • file

In this post we will dig into various ways of using the secrets along with the operation from security perspective. So, please read till the end to get idea of various ways. Here is the git repo with all Dockerfiles used in this post: https://github.com/dwdraju/docker-build-time-secrets

Way 1(Passing environment variable on Dockerfile)

# Dockerfile.1
FROM alpine:3.12
ENV MY_SECRET superSecret
CMD tail -f /dev/null

Build the docker and explore: docker run -it secret1 /bin/sh

/ # env
....
MY_SECRET=superSecret

Inspect image: docker inspect secret1

...
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"MY_SECRET=superSecret"
],
...

This is the simplest but absolutely not prefered way as the secret is exposed not only on version control but also anyone who can access the image can clearly see the secret. The secret is visible even on inspecting the image

Way 2(Passing build time argument and global env)

# Dockerfile.2
FROM alpine:3.12
ARG SECRET
ENV MY_SECRET $SECRET
CMD tail -f /dev/null

Build the docker: docker build -t secret2 . -f Dockerfile.2 --build-arg SECRET=superSecret

And explore: docker run -it secret2 /bin/sh

/ # env
....
MY_SECRET=superSecret

Inspect image: docker inspect secret1

...
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"MY_SECRET=superSecret"
],
...

In this way, the secret is out of version control but still is clearly visible for image user as well as on inspecting.

Way 3(Passing build time argument and using inside context)

The process is similar to way2 using build arg but we don’t define global ENV

# Dockerfile.3
FROM alpine:3.12
ARG SECRET
RUN export MY_SECRET=$SECRET && echo $MY_SECRET > /secret
CMD tail -f /dev/null

Build the docker: docker build -t secret3 . -f Dockerfile.3 --build-arg SECRET=superSecret

And explore: docker run -it secret3 /bin/sh

/ # env
....
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

There is no secret but can use the secret within the RUN context. The secret can also be written to file by following way:

# Dockerfile.3.1
RUN export MY_SECRET=$SECRET && echo $MY_SECRET > /secret && **DO SOME TASK** && rm /secret

If you want to remove secret after some task within the same RUN context better to do like:

# Dockerfile.3.2
RUN export MY_SECRET=$SECRET && echo $MY_SECRET > /secret && unset MY_SECRET && **DO SOME TASK** && rm /secret && **DO SOME TASK**

But let’s inspect the image

docker inspect secret3

There is not secret !

--

--

--

DevOps | SRE | #GDE

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Automation using : — -​>>> Dockerfile+Jenkins+Github

Quickly teleport back to your Git repo’s root directory

Being an architect at the IBM Garage

When Waterfall Wins: Picking the Best-Fit Project Management Approach — Seamless.Partners

C++: Complete Developers Guide -Part 2

C++ complete developers guide part 2, preprocessor, khizaruddins khizaruddins.medium.com

Azure CDN with Azure Front Door

Amundsen Monthly Update — August 2021

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Raju Dawadi

Raju Dawadi

DevOps | SRE | #GDE

More from Medium

Automate HTTPS Certificates with Ansible Roles ft. Let’s Encrypt & CloudFlare

Custom Docker Bridge Networks— How to run Containers?

Securely exposing your Docker API

Learn Docker: Containers (2/6)