Jekyll's Docker image
Jekyll's ecosystem
I was pretty excited when I found out about Jekyll about a month ago.
It not only gives me the most of the content authoring functionality I need, it also allows me to gain nearly complete control over the site's features and aesthetics. If I knew Ruby, or if the plugins did exactly what I need, I would probably have to say "...gain total control".
The platform is extendable by means of Ruby plugins. They can greatly increase the value of this software and I find that usually they are indispensable. Anybody can create such a plugin. As I understand it, Jekyll plugins are normally shipped as gems. Gems often depend on other gems. Some gems manifest need to have non-gem binary pre-installed on you system in order to work (e.g. jekyl-assets dependency on graphicsmagick binary).
On top of that I was experimenting with some JS build tools (Gulp and Grunt namely) solely for this setup. Needless to say that required more code to be dumped into my environment. Code I don't normally need.
Jekyll with Docker
I have found experimentation with Jekyll much easier and cleaner with the use of Docker image.
It allowed me to describe my Jekyll setup as code.
I am consciously not stating infrastructure as code as there are some manual steps I need to perform to provision the infrastructure. These steps are small, need to be done once per site, they are asynchronous in nature, some cross-depend and they span across multiple cloud services. I decided not to bother.
That means I can automatically and repeatably create a container with fresh Jekyll setup, ready to fiddle with it.
It allowed me to contain the messy zone to a single directory, which is mounted in the container.
All sounds good, but I had one annoying problem with the image as it is.
Jekyll's Docker image
The Dockerfile creates a jekyll user/group as following:
1RUN addgroup -Sg 1000 jekyll
2RUN adduser -Su 1000 -G \
3 jekyll jekyll
and then changes ownership of Jekyll locations:
1RUN chown -R jekyll:jekyll $JEKYLL_DATA_DIR
all data generated by Jekyll platform in this container would be owned by Jekyll user/group. In container this translates to uid of 1000 and gid of 1000. The issue is that my host system could not use that uid/gid pair.
Instead I wanted the generated "_site" to be owned by the user which runs docker container. I didn't want to modify the Dockerfile source as it would mean complex merging in case upstream provides me with wildly different future revision. I wanted to patch it over the source.
Dockerfile with desirable uid/gid
Here's what works very well for me:
1FROM jekyll/jekyll:builder
2
3ENV TZ=Europe/London
4RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
5
6ARG to_uid
7ARG to_gid
8
9RUN usermod -u ${to_uid} jekyll && groupmod -g ${to_gid} jekyll
10
11RUN find / -user $(cat /tmp/from_uid) -exec chown ${to_uid}: {} +
12RUN find / -group $(cat /tmp/from_gid) -exec chown :${to_gid} {} +
13
14RUN apk add --update 'graphicsmagick>=1.3.27-r0' nano
Building the image requires uid/gid arguments:
1docker build --rm -t my-jekyll-image --build-arg to_uid=$(id -u) --build-arg to_gid=$(id -g) .
I am aware it is not ideal, because I am baking uid/gid in the image, while desirable uid/gid may vary for different user. Same problem may occur as with the original Jekyll image definition. At least I can now configure it though. It was a quick workaround that allowed me to continue experimentation with Jekyll.
You may notice timezone change in the image. While unrelated to uid/gid problem, this is another example of hardcoded variable. In the original Dockerfile, timezone is set to America/Chicago. I was getting annoyed about timestamp differences so fixed it to my timezone.