How to securely git clone/pip install a private repository into my docker image?

As explained in "Securely build small python docker image from private git repos", you would need to use, with Docker 18.09+

  • --ssh
    You can use the --ssh flag to forward your existing SSH agent key to the builder. Instead of transferring the key data, docker will just notify the builder that such capability is available.
    Now when the builder needs access to a remote server through SSH, it will dial back to the client and ask it to sign the specific request needed for this connection.
    The key itself never leaves the client, and as soon as the command that requested the access has completed there is no information on the builder side to reestablish that remote connection later.

  • Secrets:
    Provides a mount option during the build at /var/run/secrets available only for the command that used it and is not included in the created layer.

That is:

docker build --ssh github_ssh_key=/path/to/.ssh/git_ssh_id_rsa .

only the agent connection is shared with that command, and not the actual content of the private key.
no other commands/steps in the Dockerfile will have access to it.

The Dockerfile, in a multistage first step, would give a key name github_ssh_key so we can use it when we invoke docker build:

RUN --mount=type=ssh,id=github_ssh_key pip wheel \
    --no-cache \
    --requirement requirements.txt \

The OP Jesus Garcia did report (in the comments) making it work:

I had to use 2 separate RUN commands.

I'm not sure if it's a limitation of this new feature, or the way I was trying to string together multiple commands in my RUN but I kept getting a publickey permission denied error when I added it as other commands && /bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" vs RUN --mount=type=ssh,id=github_ssh_key pip install private-repo && more commands ...

This worked for me with docker 19.03.5 (but should work with 18.09+):

Say your private repo is on Github, and you want to pip install it as part of a docker build. The ssh key to the repo is located on the host at ~/.ssh/my_key.

In the Dockerfile:

RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan >> ~/.ssh/known_hosts
RUN --mount=type=ssh pip install git+ssh://[email protected]/user/repo.git

Then, on the host:

eval `ssh-agent`
ssh-add ~/.ssh/my_key
docker build --ssh default=$SSH_AUTH_SOCK .

Despite using modern (19.03.8) Docker, neither of the above solutions worked for me (even after prepending DOCKER_BUILDKIT=1) without an extra line I found in Alexandra Ulsh's blog post, which I think is significant enough to deserve an extra answer rather than being buried in the comments.

Though the --secret flag appears in a production version of Docker, there are a few hints that support is still somewhat experimental.

For example, the first line of a Dockerfile using build secrets must be # syntax = docker/dockerfile:1.0-experimental. Without this line you’ll get the error failed to create LLB definition: Dockerfile parse error line 6: Unknown flag: mount. This line enables the Docker CLI to use the “experimental Dockerfile frontend” for Moby BuildKit.

TL;DR add the commment # syntax = docker/dockerfile:1.0-experimental at the top of your Dockerfile, then follow Dave Rejkher's answer.