Docker is a great tool for packaging an application and its dependencies. However, sometimes some of those dependencies are stored in private repositories, which requires special handling. The purpose of this article is to discuss in detail the required steps for accessing private Git repositories during a Docker image build.
Attention: If you are following the steps outlined below you’ll be leaking your private keys into your Docker image. Make sure that you sanitize your docker image from any private keys BEFORE sharing the Docker image with any 3rd party which should not have access to your private Git repositories.
As a first step you need to generate a public/private key pair using ssh-keygen.
ssh-keygen -t rsa -b 4096 -C "name@domain.com" -f MY_SSH_KEY
Doing so will generate two files: MY_SSH_KEY which contains the private key and MY_SSH_KEY.pub which contains the public key. Make VERY sure that the private key stays private, do not upload it to GitHub or anywhere else. Now upload your generated public key as a deploy key to your private GitHub repository (my_org/my_private_repo) which you can do in the “Settings -> Deploy keys” menu.
If you were to clone a public Git repository during a Docker image build you’d just do
git clone https://my_org/my_private_repo
. However, this won’t work for a private Git repository. In order to be able to clone a private Git repository during your Docker image build you need to add the following lines to your Dockerfile:
RUN mkdir -p ~/.ssh && chmod 600 ~/.ssh
RUN touch ~/.ssh/known_hosts && chmod 600 ~/.ssh/known_hosts
RUN eval "$(ssh-agent -s)"
You will need to pass the private repository key generated in the first step to Docker using build variables. Repeat the following steps for each private Git repository that you need to clone:
ARG MY_PRIVATE_REPO_PRIVATE_KEY
RUN echo "${MY_PRIVATE_REPO}" > ~/.ssh/my_private_repo_id_rsa && chmod 600 ~/.ssh/my_private_repo_id_rsa && \
echo "Host github.com-my_private_repo" >> ~/.ssh/config && \
echo " Hostname github.com" >> ~/.ssh/config && \
echo " IdentityFile ~/.ssh/my_private_repo_id_rsa" >> ~/.ssh/config
By invoking ssh-keyscan you can ensure that the github.com domain is accepted.
RUN ssh-keyscan github.com >> ~/.ssh/known_hosts
Since the private SSH key is now known inside the Docker image you can proceed to clone the private repository via SSH using the host (github.com-my_private_repo) specified above.
RUN git clone --recursive --depth 1 git@github.com-my_private_repo:my_org/my_private_repo.git
The only thing that is left to do is to pass the content of the private key via build variable when invoking the docker build command.
docker build \
--tag my_docker_image \
--build-arg MY_PRIVATE_REPO_PRIVATE_KEY=$(cat MY_SSH_KEY) \
.