A Better Way to Handle Build-Time Secrets in Docker

Passing build-time variables to Docker is a solvable problem. However, if you want that data to leave no traces in the image, it’s another story. For example, when you want to access private SSH repositories during a build.

You had to watch out not to leak any secrets. Packing lots of commands into a single line, making sure to clean up with squashing (nah), using multi-stage builds to keep secrets in non-public files (okay), or coming up with elaborate schemes to access those secrets securely.

A Simpler Way

Docker BuildKit brought along cool new features. One of them, is the secret mount type can give a single RUN command access to one or multiple secrets without leaving behind traces inside of the file system if used right. You can specify a secret from a file when running your build command:

docker build --secret id=yoursecret,src=/host/secret/file/path

You can give single RUN instructions access to this secret. By default this creates a file inside of /run/secrets/secretid, but you can also specify a target path of your choice.

RUN --mount=type=secret,id=yoursecret ...
RUN --mount=type=secret,id=yoursecret,target=/target/path/to/secret ...

The file is created and cleaned up automatically so it won’t leave behind any traces in the final layer, unless you write the exact same data to disk yourself.

In Conclusion

If you want to pass secret information to your Docker build, make sure to give BuildKit and its secret mount type a look. You’ll be able to access your secrets during specific RUN commands, and if your command doesn’t put traces into the image layer, your secrets are safer than before.

One more thing: if you want to handle SSH credentials, there’s another new BuildKit feature which could help you even better. You can read more here.