304 North Cardinal St.
Dorchester Center, MA 02124
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 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.
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.
It looks simple and clean. I am curious about the theme and found that it’s built using Just the Docs; Jekyll theme.
Let’s start with actual deployment…
Please make sure you should fulfill the below requirements before proceeding to the actual deployment.
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.
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 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.
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 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 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.”
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
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
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.
sudo mkdir -p jekyll
Please watch the below video for Glusterfs Installation
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.
sudo mkdir -p jekyll
sudo touch jekyll.yml
jekyll.yml created earlier with nano editor using
sudo nano jekyll.yml
Copy and paste the below code in
Here is the
docker compose file for
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
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
/mnt/jekyll(container folder is mapped to our local folder via the
volumesoption in the
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 <jekyllcontainername or id> bash
Run below command on Jekyll container to generate Gemfile for our static site
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
_configfiles 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
Postsfolder of our Jekyll site structure,
servethe 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… 🙄