I have an app that executes various fun stuff with Git (like running git clone & git push) and I'm trying to docker-ize it.
I'm running into an issue though where I need to be able to add an SSH key to the container for the container 'user' to use.
I tried copying it into /root/.ssh/
, changing $HOME
, creating a git ssh wrapper, and still no luck.
Here is the Dockerfile for reference:
#DOCKER-VERSION 0.3.4
from ubuntu:12.04
RUN apt-get update
RUN apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install nodejs -y
ADD . /src
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
RUN cd /src; npm install
EXPOSE 808:808
CMD [ "node", "/src/app.js"]
app.js
runs the git commands like git pull
If you don't care about the security of your SSH keys, there are many good answers here. If you do, the best answer I found was from a link in a comment above to this GitHub comment by diegocsandrim. So that others are more likely to see it, and just in case that repo ever goes away, here is an edited version of that answer:
Most solutions here end up leaving the private key in the image. This is bad, as anyone with access to the image has access to your private key. Since we don't know enough about the behavior of
squash
, this may still be the case even if you delete the key and squash that layer.We generate a pre-sign URL to access the key with aws s3 cli, and limit the access for about 5 minutes, we save this pre-sign URL into a file in repo directory, then in dockerfile we add it to the image.
In dockerfile we have a RUN command that do all these steps: use the pre-sing URL to get the ssh key, run npm install, and remove the ssh key.
By doing this in one single command the ssh key would not be stored in any layer, but the pre-sign URL will be stored, and this is not a problem because the URL will not be valid after 5 minutes.
The build script looks like:
Dockerfile looks like this:
In a running docker container, you can issue ssh-keygen with the docker -i (interactive) option. This will forward the container prompts to create the key inside the docker container.
This issue is really an annoying one. Since you can't add/copy any file outside the dockerfile context, which means it's impossible to just link ~/.ssh/id_rsa into image's /root/.ssh/id_rsa, and when you definitely need a key to do some sshed thing like git clone from a private repo link..., during the building of your docker image.
Anyways, I found a solution to workaround, not so persuading but did work for me.
in your dockerfile:
a script to do in one shoot:
anytime you have to run a container from this image with some ssh requirements, just add -v for the run command, like:
docker run -v ~/.ssh/id_rsa:/root/.ssh/id_rsa --name container image command
This solution results in no private key in both you project source and the built docker image, so no security issue to worry about anymore.
Docker containers should be seen as 'services' of their own. To separate concerns you should separate functionalities:
1) Data should be in a data container: use a linked volume to clone the repo into. That data container can then be linked to the service needing it.
2) Use a container to run the git cloning task, (i.e it's only job is cloning) linking the data container to it when you run it.
3) Same for the ssh-key: put it is a volume (as suggested above) and link it to the git clone service when you need it
That way, both the cloning task and the key are ephemeral and only active when needed.
Now if your app itself is a git interface, you might want to consider github or bitbucket REST APIs directly to do your work: that's what they were designed for.
Forward the ssh authentication socket to the container:
Your script will be able to perform a
git clone
.Extra: If you want cloned files to belong to a specific user you need to use
chown
since using other user than root inside the container will makegit
fail.You can do this publishing to the container's environment some additional variables:
After you clone you must execute
chown $OWNER_USER:$OWNER_GROUP -R <source_folder>
to set the proper ownership before you leave the container so the files are accessible by a non-root user outside the container.You can also link your .ssh directory between the host and the container, I don't know if this method has any security implications but it may be the easiest method. Something like this should work:
Remember that docker runs with sudo (unless you don't), if this is the case you'll be using the root ssh keys.