Configure a Docker Container to Automatically Pull from GitHub Using OAuth

By | October 29, 2016


One common situation I have run into on different projects is how to instruct my Docker containers to automatically clone or pull from a private GitHub repository when they’re built. The goal of this tutorial is to pull together various references I found into a single document for what I needed to do which is to spin up a rails app using code in a private repo on GitHub.

In this tutorial we will go through how to acquire an OAuth token from GitHub to access your repositories in an automated fashion and then use that in a Dockerfile to bring up a basic Ruby-on-Rails application using the Phusion Passenger 3.0 webserver.

Create GitHub OAuth Token

Developers have a few methods they can use to access their repositories on GitHub. Using personal access tokens allows you to forgo having to provide a username and password when making a request. This is the recommended approach to automating the synchronization of your code. It is also an easier method than hacking together one of the many SSH key solutions you might find elsewhere on the web.

These instructions assume that you host your repos with GitHub and that you have private repos you would like to pull or clone automatically. While being logged into your GitHub account you can obtain an OAuth token by navigating to Settings –> Applications –> Generate New Token.

Be aware that when GitHub generates the token it will only show it to you once. When you browse away from the page you will not be able to view the token again therefore it’s a good idea to make note of what it is before proceeding onto the Dockerfile steps. If you lose the token you will need to regenerate it. You can also use this interface to revoke tokens.

Create the token so that it has the appropriate scope for what you require. The defaults should be fine for this example.


Now that you have an OAuth token it’s relatively easy to construct the HTTPS URL to pull or clone from your private repo(s). This can be done in the following fashion:

git clone -b docker https://<token>:[email protected]/StackPointCloud/myapp.git /myapp/

The <token>:x-oauth-basic is where the magic happens. It should be noted that we are using personal access tokens which are a bit different than registered application tokens.

Now, let’s turn to our Dockerfile:

# Let's use the official Passenger container.
FROM phusion/passenger-ruby19:latest
MAINTAINER Matt Baldwin "[email protected]"

# Clone our private GitHub Repository
RUN git clone -b docker https://<token>:[email protected]/StackPointCloud/myapp.git /myapp/
RUN cp -R /myapp/* /home/app/
RUN chown app:app -R /home/app/

# Setup Gems
RUN bundle install --gemfile=/home/app/Gemfile

# Setup Nginx
ENV HOME /root
RUN rm -f /etc/service/nginx/down
ADD myapp /etc/nginx/sites-enabled/
RUN rm /etc/nginx/sites-enabled/default

# Setup Database Configuration. Since we use both we'll add both here.
# This is done to preserve Docker linking of environment variables within Nginx.
ADD postgres-env.conf /etc/nginx/main.d/postgres-env.conf
ADD mongodb-env.conf /etc/nginx/main.d/mongodb-env.conf

# Clean-up
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /myapp/

CMD ["/sbin/my_init"]
EXPOSE 80 443

In the first section we’re instructing Docker to use Phusion’s Ruby 1.9.3 image. If you don’t have it locally it will be pulled down.

We then clone our desired branch — in our case docker — to a new directory myapp at the root of the file system. All content is then copied over to the default /home/app location for the Passenger 3.0 container. The bundle install installs any required gems we may need.

Our Nginx configuration is taken from Passenger’s Docker documentation, but looks like this:

server {
    listen 80;
    root /home/app/public;

    passenger_enabled on;
    passenger_user app;

    # For Ruby 1.9.3 (you can ignore the "1.9.1" suffix)
    passenger_ruby /usr/bin/ruby1.9.1;

We also add a few environment configuration files to ensure our Docker link names are exposed in Nginx, too.

Once all that is done my_init is ran when the container spins up with 80 and 443 exposed.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.