18 Sep, 2016

It is quite common situation when you are building Docker images: some secret value/file is needed (temporary, for the duration of the build), and you are puzzled how to pass it w/o over-exposing, and make it accessible down the road, when the image becomes publicly available.

Use case: SSH keys required to access private GitHub repository

Couple of days ago, I needed to build image for Ethereum (this had to be custom build that included code from our private repository).

Accessing private GitHub repositories is easy: all you need is to generate RSA key, and add its public part as deploy key to GitHub repository of interest (see Repository Settings).

Then on client side, you need to load private part of the key and…well, that’s it - you will be able to clone from the private repository.

Problem

The problem is that if you ADD private key to your Docker image (in Dockerfile), it will be persisted as a layer. And even if you then remove the private key (once you are done pulling from the repository), your private key will still be available (that’s how layers work - key will be missing from the latest layer, but still available in the original layer it was added to). And that is a huge no-no!

There are number of solutions available:

My solution

Which is pretty simple: expose any required artifacts using local web-server, and fetch them into the image using wget or similar.

Without further ado, here is Dockerfile:

FROM alpine:3.4

RUN \
  apk add --update git openssh-client && \

  # add SSH key
  wget -O /tmp/id_rsa http://192.168.99.1:8080/some_id_rsa && \
  chmod 600 /tmp/id_rsa && \
  eval $(ssh-agent) && \
  echo -e "StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \
  ssh-add /tmp/id_rsa && \

  # clone some private repo
  git clone --depth 1 --branch develop git@github.com:farazdagi/some-repo.git  && \

  # install and cleanup
  # ..some installation instructions
  apk del git openssh-client && \
  rm /tmp/id_rsa

EXPOSE 8545

ENTRYPOINT ["/foo"]

Now, the last thing before we docker build is to make sure that RSA keys are exposed indeed.

You can use Python’s SimpleHTTPServer or PHP’s bundled server, or whatever you have experience with.

I’ve used PHP’s internal server:

cd ~/folder-that-has-your-deploy-id-rsa
run -S 192.168.99.1:8080 # that's it, all files in the directory are exposed

The benefits are immense:

References

Follow @farazdagi Tweet