Updating the Gemfile while running Rails in a Docker container
Running Rails under Docker is a pretty new concept for some. It is understandable since Rails relies heavily on convention. A lot of patterns performed while developing are well established in the community. It’s easy to become accustomed to doing things “just because that’s how it’s always been done”. This blog post is the first in a series that hopes to untangle some of the issues you may experience when transitioning to Docker.
One of the most simplest tasks a Rails developer (or any Ruby dev for that matter) performs is to update the Gemfile. It seems like such a trivial task, yet its very easy to trip yourself up without having a deeper understanding of how Docker works.
An important concept one must keep in mind while working with Docker is the utilization of Layers. For each step in a Dockerfile, a layer is stored that is built on top of the previous. This is relevant to the Gemfile because the step in which you install your Gems (via
bundle install), a layer is cached. Each time your container starts, the filesystem will have the specified gems installed.
Now why is this important? Because anything you do to the filesystem in a running container will not persist in subsequent runs (except when you use volumes). This becomes an issue when you perform add a new gem and perform a
bundle update in the running container. The gem may install, however, once you restart your container, the new gem will not exist. This is because the container filesystem is built on Layers, and the build contains the layer with the old set of gems.
The work around? Rebuild your image! Once you issue the
docker build command again, the Gemfile would have changed, thus triggering the cached layer to expire. Docker will then install the new gems and cache a new layer.
Step by Step #
To ensure you are updating your gems/Gemfile correctly, keep it mind it is now a two step process.
bundle installin the running container. This is needed so that your Gemfile.lock is updated with the changes (assuming you have a volume mounted to your app)
- Rebuild your image
docker build. This will run through the build process, invalidate the old cached layer with the outdated gems, and create a new layer with the correctly installed gems.
So there you have it, a slight complication when developing a Ruby on Rails application under Docker. It may seem cumbersome at first, but hopefully your Gemfile will reach a certain stable point where these updates will be far and few in between. There are other gotchas working with Docker when coming from a more traditional setup. I hope to uncover those with upcoming blog posts. Stay tuned!
Hope you found this post useful, as always, feel free to reach out to me with any questions or concerns.