Jekyll-dockerimage: Bundler and Gemfile

2 minute read

What is bundler?

Bundler is a tool that can be used to manage and version dependencies between modules and libraries for Ruby language. I use Bundler commands regularly, e.g. to build my blog and put it live on the server.

If I want to build locally, I type

bundle exec jekyll serve --incremental --future

into the console. This command tells Bundler to run the jekyll application in server mode and provides it with parameters that prevent jekyll from completely rebuilding every time a file is changed and still create pages that have not yet been published.

bundler in the CI pipeline

I also use Bundler as part of a Jekyll Docker image to publish my site, as I have often linked to, e.g. when moving to self-hosted. Since switching to a new version of the blog software lately, I have been seeing puzzling errors in my CI pipeline. Locally however, the system builds flawlessly. I have documented how to address and fix such errors here.

“There was an error while trying to write to /path/to/Gemfile.lock” - CI console output

No write permissions

Like the Jekyll user, Bundler itself can only read files on my CI and cannot write them. I can fix this for the Jekyll output with chown, but I don’t want to allow bundler to do this: I require Gemfile.lock to remain identical between my local build environment and the CI so that I can fix errors in advance.

Specification file for bundler

The Gemfile.lock file contains all dependencies of the application used, including version numbers and sources. If only the source code of the application plus this file is provided, bundler can pull a specific version of all dependencies during build time, allowing to work with similar requirements regardless of machine and version.

Troubleshooting

A first attempt to fix the issue by aligning all versions between local and CI failed. The second attempt, to give the Jekyll user write permissions to the Gemfile.lock, also failed. The third attempt led me to the Bundler website, where I took a closer look at the parameters, keyword “frozen”.

The fact is that you can prohibit bundler from rewriting the Gemfile.lock. To do this, use the command

bundle config set frozen true

According to its documentation, processing is aborted as soon as the file is about to be rewritten.

Although I had added this command to my yaml file in the CI, the build failed again. The trigger was the same library nokogiri as before, but the error message was now much more helpful:

Image: jekyll build error due to build platform incompatibility between local and remote.

Optimize Gemfile.lock for different environments

So I follow the suggestion and execute the desired command on my local machine:

bundle lock --add-platform x86_64_musl # my CI runner's environment

Note: musl is a libc-implementation for Linux.

My lockfile now has the following entry:

nokogiri (1.18.10-x86_64-linux-musl)

With this error fixed, I get better portability of my web page creation setup as a side effect.

Image: successful CI run with updated dependencies