Using Docker to maintain a Ruby gem

My new way of working is:

  1. Install Docker
  2. Install Git
  3. Install Sublime Text
  4. Code !

Now maintaining a Ruby gem (library for Ruby) using docker is super easy and brings to your gem all the advantages of Docker ! (Try different version of Ruby and so on).

So I'm going to show you how I'm maintaining my gems (well starting as of now : )) using Docker.

In the case you're new to Docker I highly recommend you to have a look at my previous article Containerize with Docker and all my Docker articles.

Maintaining a gem with Docker

I will use as an example the gem switchery-rails.
This gem brings the Switchery Javascript library to your Rails application.

When a new release is published on Github, like recently the version 0.8.0, I want to be able to update the library without having to install Ruby and all the dependencies on my machine.

By running few commands I'm expecting to release a new version of the gem.

Dockerfile

An easy and convenient way to build Docker images is the Dockerfile. Here I'm sharing you a basic Dockerfile which could be used for any gems (where adaptation could be required):

The litaio's ruby image, which is used in the Dockerfile, is very nice as it brings Ruby only (a lot of Docker images brings Ruby but it brings a lot of other useless tools too).
The Dockerfile then installs git as required later in order to publish the gem, then it installs Bundler and finally import your gem.
The latest lines mean always prefix the commands with bundle exec and in case no command is given use rake -T which shows all the available tasks (as a kind of help).

Build & use of the image

Build

First you need to build the image in order to use, so after having cloned the repository from Github I'm going to the folder and build the image:

$ git clone git@github.com:YourCursus/switchery-rails.git
$ cd switchery-rails/
$ sudo docker build -t zedtux/switchery-rails .

Now I run the image without parameters in order to see the available Rake tasks I can use:

$ sudo docker run --rm zedtux/switchery-rails
[sudo] password for zedtux: 
rake build             # Build switchery-rails-0.1.0.gem into the pkg directory
rake install           # Build and install switchery-rails-0.1.0.gem into system gems
rake install:local     # Build and install switchery-rails-0.1.0.gem into system gems without network access
rake release           # Create tag v0.1.0 and build and push switchery-rails-0.1.0.gem to Rubygems
rake update_switchery  # Update the Switchery Javascript and CSS files

You will recognize the standard tasks from Bundler (build, install, install:local and release) and a custom task I did in order to automate the update of the Switchery library.
(The --rm flag means to delete the Docker image when exiting otherwise you will have a messy Docker image list and it's taking space)

Update the Javascript library

Before to execute the rake task to update the Switchery, I have to update the version I want to update to.
When creating a gem using Bundler, it creates a version.rb file where you define the value of the VERSION constant. This constant is used by the rake task in order to know which version to download so we have to update it with the right version.

Now I want to execute the rake task update_switchery and have the file updated on my disk (out of the Docker container) so I need to mount a volume to my current folder:

$ sudo docker run --rm -v `pwd`:/gem/ zedtux/switchery-rails rake update_switchery
Downlading Switchery 0.8.0 ...
Done!

Now doing a git status in the current folder should shows you the version.rb file and the Switchery file(s).
A small commit and your repository is updated.

Publishing the updated gem

Now I want to execute the rake release task which:

  1. Build the gem
  2. Tag the Git repository (using the gem version) and push the tag to Github
  3. Push the gem to Rubygems.org

The Docker image will requires to access your SSH keys in order to perform the point 2 and then it will need to access your Rubygems.org credentials in order to perform the point 3.

The SSH keys are stored in ~/.ssh/ and the Rubygems.org credentials in the ~/.gem/ folder.
I'm now mounting 2 volumes for both folders and run the rake release task:

$ sudo docker run --rm -v ~/.gitconfig:/root/.gitconfig -v ~/.ssh/:/root/.ssh/ -v ~/.gem/:/root/.gem/ -v `pwd`:/gem/ zedtux/switchery-rails rake release
switchery-rails 0.8.0 built to pkg/switchery-rails-0.8.0.gem.
Tagged v0.8.0.
Pushed git commits and tags.
Pushed switchery-rails 0.8.0 to rubygems.org.

Done ! The new version of the gem is now available and you can update your project(s).

Conclusion

As you can see it's really easy and quick to use a container in order to maintain a gem.
Docker is really awesome and can do so much things ! : )