How to deploy Jekyll 4.2.0 in docker swarm behind Traefik v2.0
- Rajasekhar Gundala
- 16 Aug, 2020
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-Werner, GitHub’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 Jekyll, Ruby, 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.
- Docker Swarm Cluster with GlusterFS as persistent tool.
- Traefik as reverse proxy to expose micro-services to external.
- 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 Markdown, Liquid, 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 Caddy, Apache HTTP Server, Nginx, 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
- No Database – Jekyll doesn’t have a database. All posts and pages are converted to static HTML prior to publication.
- Fast – Jekyll is fast because you’re just serving up static pages and makes fever HTTP requests.
- 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.
- Stability – If a user’s site builds today, it should build tomorrow. Backwards-compatibility should be strongly preferred over breaking changes.
- 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.
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
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
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 thevolumes
option in thejekyll.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
Also edit _config.yml to include your site name, theme name, plugins, etc
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
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 andserve
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.
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… 🙄