How to deploy Jekyll 4.2.0 in docker swarm behind Traefik v2.0

How to deploy Jekyll 4.2.0 in docker swarm behind Traefik v2.0

Jekyll is a static site generator. You give it text written in your favorite markup language and it uses layouts to create a static website. You can tweak how you want the site URLs to look, what data gets displayed on the site, and more.

In this post, I am going to show you how to deploy Jekyll 4.1.1 to our Docker Swarm Cluster using the Docker Compose tool.

Jekyll is a simple blog-aware static site generator for personal, project, or organization sites. Written in Ruby by Tom Preston-WernerGitHub’s co-founder, it is distributed under the open source MIT license

The story behind how I learned Jekyll

It’s very interesting. One day I was searching for Single Sign On (SSO) solutions for Docker Swarm Cluster that integrates with Traefik.

Then I found Authelia and KeyClock for the purpose. Then I opened the Authelia documentation site and was impressed with that site.

It looks simple and clean. I am curious about the theme and found that it’s built using Just the Docs; Jekyll theme.

Then I started learning JekyllRuby, and RubyGems (the software required to built Jekyll sites)

learn more about Jekyll using the official web site and Wikipedia

Let’s start with actual deployment…

Prerequisites

Please make sure you should fulfill the below requirements before proceeding to the actual deployment.

  1. Docker Swarm Cluster with GlusterFS as persistent tool.
  2. Traefik as reverse proxy to expose micro-services to external.
  3. Database stack to host application databases.

Introduction

If you are looking for a static site generator to generate a static website using your data and templates, then Jekyll is a first-class citizen.

A static website is pre-rendered; means all the files (HTML, CSS, Javascript, and images) exist as is, and do not need to be processed on the server level like CMS’s like WordPress, Joomla, Drupal…

Jekyll is a static site generator. You give it text written in your favorite markup language and it uses layouts to create a static website. You can tweak how you want the site URLs to look, what data gets displayed on the site, and more.

No more databases, comment moderation, or pesky updates to install – just your content.

Jekyll uses MarkdownLiquid, HTML & CSS to generate Static sites that are ready for deployment.

Jekyll is blog-aware, which means permalinks, categories, pages, posts, and custom layouts are all first-class citizens here.

Transform your plain text into static websites and blogs.

Why is Jekyll

Instead of using databases, Jekyll takes the content, renders Markdown or Textile and Liquid templates, and produces a complete, static website ready to be served by CaddyApache HTTP ServerNginx, or another web server.

Jekyll is the engine behind GitHub Pages, a GitHub feature that allows users to host websites based on their GitHub repositories for no additional cost.

Jekyll is flexible and can be used in combination with front-end frameworks such as Bootstrap, Semantic UI, and many others.

Jekyll sites can be connected to cloud-based CMS software such as CloudCannon, Forestry, Netlify, or Siteleaf, enabling content editors to modify site content without having to know how to code.

Jekyll is a Ruby Gem that can be installed on most systems.

Jekyll Features

Jekyll is not magic. A user should be able to understand the underlying processes that make up the Jekyll build without much reading.

It should do only what you ask it to and nothing more. When a user takes a certain action, the outcome should be easily understandable and focused.

The out-of-the-box experience should be that it “just works.”

Run gem install jekyll and it should build any Jekyll site that it’s given. Features like auto-regeneration and settings like the markdown renderer should represent sane defaults that work perfectly for the vast majority of cases.

Jekyll features include

  1.  No Database – Jekyll doesn’t have a database. All posts and pages are converted to static HTML prior to publication.
  2.  Fast – Jekyll is fast because you’re just serving up static pages and makes fever HTTP requests.
  3.  Content is king – Jekyll focuses on content first and foremost, making the process of publishing content on the Web easy. Users should find the management of their content enjoyable and simple.
  4.  Stability – If a user’s site builds today, it should build tomorrow. Backwards-compatibility should be strongly preferred over breaking changes.
  5.  Small & extensible – The core should be kept to features used by at least 90% of users–everything else should be provided as a plugin. New features should be shipped as plugins and focus should be put on creating extensible core API’s to support rich plugins.

Persist Jekyll Data

Containers are fast to deploy and make efficient use of system resources. Developers get application portability and programmable image management and the operations team gets standard run time units of deployment and management.

With all the known benefits of containers, there is one common misperception that the containers are ephemeral, which means if we restart the container or in case of any issues with it, we lose all the data for that particular container. They are only good for stateless micro-service applications and that it’s not possible to containerize stateful applications.

I am going to use GlusterFS to overcome the ephemeral behavior of Containers.

I already set up a replicated GlusterFS volume to have data replicated throughout the cluster if I would like to have some persistent data.

The below diagram explains how the replicated volume works.

GlusterFS Replicated Volume

Volume will be mounted on all the nodes, and when a file is written to the /mnt/ partition, data will be replicated to all the nodes in the Cluster

Note

In case of any one of the nodes fails, the application automatically starts on other node without loosing any data and that’s the beauty of the replicated volume.

Persistent application state or data needs to survive application restarts and outages. We are storing the data or state in GlusterFS and had periodic backups performed on it.

We will use a backup of the volume to spin a new application container anywhere else in case of unexpected issues occur in the current environment.

I am going to persist /srv/jekyll directory of Jekyll for disorder recovery.

Create folder in /mnt directory to persistent Jekyll data folder.

cd /mnt
sudo mkdir -p jekyll

Tip

Please watch the below video for the GlusterFS Replicated Volume Setup.

Prepare Jekyll Environment

Create a folder in /opt directory to place the configuration file, i.e, .yml file for Jekyll.

Use the below command to create the folder.

cd /opt
sudo mkdir -p jekyll
cd jekyll
sudo touch jekyll.yml

Jekyll Docker Compose

Open jekyll.yml created earlier with nano editor using sudo nano jekyll.yml

Copy and paste the below code in jekyll.yml

Here is the docker compose file for jekyll.

version: "3.7"

services:
  jekyll:
    image: jekyll/jekyll:latest
    command: jekyll serve --watch --force_polling --verbose
    volumes:
      - /mnt/jekyll:/srv/jekyll
    environment:
      - JEKYLL_ENV=production
    networks:
      - proxy
    ports:
      - "4000:4000"

    deploy:
      placement:
        constraints: [node.role == worker]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=proxy"
        - "traefik.http.routers.jekyll.rule=Host(`jekyll.example.com`)"
        - "traefik.http.routers.jekyll.tls=true"
        - "traefik.http.routers.jekyll.tls.certresolver=default"
        - "traefik.http.routers.jekyll.entrypoints=websecure"
        - "traefik.http.services.jekyll.loadbalancer.server.port=4000"
volumes:
  jekyll:
    driver: "local"
networks:
  proxy:
    external: true

Deploy Jekyll using Docker Compose

Now it’s time to deploy our docker-compose file above, jekyll.yml using the below command

docker stack deploy --compose-file jekyll.yml jekyll

You can give it any name for the stack. I just named it as jekyll

Check the status of the stack by using docker stack ps jekyll

When we deploy Jekyll to docker swarm, it creates _site folder in /srv/jekyll means in /mnt/jekyll (container folder is mapped to our local folder via the volumes option in the jekyll.yml

Now we have to create a folder structure doe our Jekyll site

We have to run some commands on the Jekyll docker container to create the folder structure and serve our site.

Launch our worker node (we targeted our Jekyll container to a worker node in compose file)

In order to find the container id, run docker ps on the worker node

Log into Jekyll docker container using the below command

docker exec -it <jekyll containername or id> bash

Run below command on Jekyll container to generate Gemfile for our static site

bundle init

Now open Gemfile and update your site details (theme you are going to use and the plugins ) and run the below command to build our site

Sample Gemfile

Also edit _config.yml to include your site name, theme name, plugins, etc

Config file basic details

Config file other details

Gemfile and _config files are heart for any Jekyll site. You need specify theme and plugins, other configuration options in these files.

Now build the site using the below command.

bundle exec jekyll build

Based on the selected theme, the above command creates the below structure and locks the Gemfile file

In the future, if you want to add more plugins to the site, you can add and bundle them again using bundle install command to install extra plugins

After that, you have to build using bundle exec jekyll build

Folder structure after build command

Now run the below command to serve our site

bundle exec jekyll serve

If you use Jekyll for personal blog, you need place your articles (markdown files, .md) in Posts folder of our Jekyll site structure, build it and serve the site every time.

Now open any browser and type jekyll.example.com (whatever host URL used in the Jekyll configuration in the docker-compose file) to access the instance.

Make sure that you have DNS entry for your application (jekyll.example.com) in your DNS Management Application.

You will be greeted with the Jekyll site with Just The Docs theme.

Just the docs theme

I came across this site and found a lot of static site generators. But I found Jekyll is easy to learn and deploy.

If you enjoyed this tutorial, please give your input/thought on it by commenting below. It would help me to bring more articles that focus on Open Source to self-host.

Stay tuned for other deployments in coming posts… 🙄