Safely Building Docker Images with Private Ruby Gems Using Github Actions

Jake Myers
Red Squirrel
Published in
2 min readApr 19, 2023
Photo by Dayne Topkin on Unsplash

I recently worked on a project that utilized several private Ruby Gems hosted in a GitHub repo. To build the projects using Docker, we had to incorporate a personal GitHub SSH key into the Docker container for access to the private repositories. This approach felt insecure, so after researching and testing, a more streamlined solution emerged. Here are the steps to optimize the process without unnecessarily exposing secrets in your Docker container:

Step 1: Create a Registry

Photo by Joshua Fuller on Unsplash

Establish a RubyGems registry on GitHub within your organization and transfer the gems to it. This enables referencing gems in the Gemfile as follows:

source "https://rubygems.pkg.github.com/my_org" do
gem "my_gem"
gem "my_gem_two"
gem "my_other_gem"
end

Instead of this method:

gem "my_gem", git: "git@github.com:my_org/my_gem.git"
gem "my_gem_two", git: "git@github.com:my_org/my_gem_two.git"
gem "my_other_gem", git: "git@github.com:my_org/my_other_gem.git"

This looks way nicer already!

Now, SSH keys are no longer needed to access the gems. Though a personal access token can be used, it is preferable not to link infrastructure to personal accounts. Additionally, personal tokens stored in a Docker container can pose a security risk, and expiring tokens must be managed. Fortunately, there’s a secure solution using Github Actions.

Step 2: Implement GitHub Actions

Photo by Roman Synkevych 🇺🇦 on Unsplash

GitHub Actions allow for the installation of private gems in a container without utilizing personal keys. This is possible because GitHub registries permit specifying organization repositories with registry access.

Bundler requires a token to access the private registry. By setting the BUNDLE_RUBYGEMS__PKG__GITHUB__COM environment variable, the token can be accessed. While a Personal Access Token is used locally, GitHub Action workflows provide an alternative. The repository’s GITHUB_TOKEN secret is automatically set in the background. After granting repository access to the RubyGems registry, the workflow action is configured to supply the token to the Dockerfile for building.

Using the — build-arg argument, the non-personal token can be passed into the Docker build:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build --build-arg GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} .

In your Dockerfile, it can be accessed like this:

ARG GITHUB_TOKEN
RUN BUNDLE_RUBYGEMS__PKG__GITHUB__COM=${GITHUB_TOKEN} bundle install

This solution allows for the installation of private gems in your Docker containers without exposing personal secrets. Hooray!

--

--