Recently I’ve introduced private Github repo the project’s Gemfile.

# Gemfile

# ...
gem 'myprivategem', git: '[email protected]:myorg/myprivategem.git'
# ...

We are using Docker to build our Ruby on Rails application so no surprise that we got “no permission to repository” from bundler when building our Docker image.

solution 1 - (BAD) ssh key to Docker image

One way how this would be possible to fix is to copy ssh keys to Docker container. But this is a big security no-no as anyone who will get a hand on that docker image can retrieve the ssh private key. This even apply if you delete the key in next line, as Docker image layers consist of root-file system changes => the key will still be retrievable from previous layer of the docker image.

So do yourself a favor and don’t do this !

solution 2 - https credentials

Another way is to use https://github.com/... format instead of [email protected]:... format and pass the credentials. In order to do this first you need to generate personal Github access token

Then you need to pass the credentials to Gemfile similar way like this:

# Gemfile

# ...
gem 'myprivategem', git: 'https://myuser:[email protected]/myorg/myprivategem.git'
# ...

Now this is not necessary bad approach as long as you don’t commit your Gemfile like this to source control (git).

You can pass build argument to docker build In Dockerfile, then you can pass env variable to Gemfile when you run bundle install.

# build script on the build box
docker build -t=live-20170502 --build-arg github_token=xxxxxxxgeneratedxxxxxtokenxxxxxxxxx .
# Dockerfile

# ...
ARG github_token
RUN GITHUB_TOKEN=$gitub_token bundle install
# ...
# Gemfile

# ...
gem 'myprivategem', git: 'https://#{ENV['GITHUB_TOKEN']}:[email protected]/myorg/myprivategem.git'
# ...

solution 3 - Bundler provider credentials

Now the prev. approach is repetitive and messy for development environment. That’s why you can set your “provider” credentials via bundle config

development machine:

Therefore all that developers in their development machines need to do is:

  1. create personal Github access token and set permissions to read repo

  2. run this:

bundle config  github.com myuser:xxxxxxxgeneratedxxxxxtokenxxxxxxxxx

build machine:

As for the production docker build would look like this:

# build script on the build box
docker build -t=live-20170502 --build-arg github_token=xxxxxxxgeneratedxxxxxtokenxxxxxxxxx .
#Dockerfile

# ...
ARG github_token
RUN bundle config github.com mydeploymentuser:$github_token && (bundle install --without test development) && bundle config --delete github.com
# ...
# Gemfile

# ...
gem 'myprivategem', git: 'https://github.com/myorg/myprivategem.git'
# ...

In this case we are setting the credentials, running the bundle install and removing the credentials is same layer. Therefore credentials will not be committed to the Docker layer. It’s similar to RUN apt-get update && apt-get install -y imagemagick && rm -rf /var/lib/apt/lists/*

resources