When building a docker image, a standard task is to clone repositories, fetch data or otherwise access servers, all of which may require login credentials, private keys or other secrets to allow access.
I was unable to find any good way to do this: all approaches either potentially expose the secret in the final image or incredibly clumsy and ugly to implement.
Is there one proper way how to do this? For example if I want to clone a repository from server X as part of building my docker image and doing that requires a private key, how exactly am I supposed to do this?
Unfortunately it’s a long standing issue without one clear solution. See for instance https://github.com/docker/docker/issues/13490.
If all you need is SSH access to certain repositories one simple solution would be to git clone
the repositories ahead of time (perhaps in some type of outer build script / Makefile) and then COPY
them into the image in the Dockerfile
. As of today there’s nothing like SSH agent which can run in containers though (at least without a few ugly or dangerous hacks).
Thank you - this pretty much confirms what my impression was though I wanted to make sure since I thought that this is so fundamental and probably common that there simply has to be a better solution
What you suggest is essentially what we ended up doing, but it feels like the wrong approach since it now adds another script to the dockerfile script. The Dockerfile way of setting up the image is in my opinion what is really brilliant about Docker: one has a “source code” for generating a system. But because of this flaw, now we need at least two separate sourcecodes and things are messy again.
I think a simple way to make things like this easier would be if there was a way to mount a host directory as a temporary directory that does not become part of the image during the build - that temporary directory could then hold private keys or other secrets to be used during the build without ever becoming a part of the image.
You still have that source code (Dockerfile + build context), it’s just separated out into another layer. At the end of the day, a pattern like this:
ADD ./myscript.sh
RUN ./myscript.sh
is conceptually similar to defining a subroutine that you call from another part of your code. Just like a large code project gets split up into many files and directories, it’s fine to do the same with a Dockerfile
.
There’s endless debate about whether or not this sort of thing should be allowed, but I encourage you to participate in the relevant GitHub threads about what would and wouldn’t work for your use case.