How to deploy Jekyll 4.2.0 in docker swarm behind Caddy v2.3
- Rajasekhar Gundala
- 15 Apr, 2021
Jekyll is a simple blog-aware static site generator for personal, project, or organization sites. 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.
In this post, I am going to show you how to deploy Jekyll as a file server behind Caddy 2.3 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
Please go through my previous post about Deploy Jekyll in Docker Swarm to learn more about Jekyll.
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
- Jekyll Dev Environment
- Caddy as reverse proxy to expose micro-services to external
Introduction
I wrote the below articles with regards to Jekyll previously. Please find the links below if you didn’t go through them. It would be good to go through the links before proceeding further.
Jekyll Dev Environment on Windows 10
Persist Jekyll Data
You must be familiar with Jekyll Dev Environment on Windows 10 article and section Build and Server the Site
After bundle exec jekyll build
there will be _site
folder created in our theme directory. All the html files will be there in _site
folder. I will be persisting _site
folder using GlusterFS and server the files using Caddy 2.3 as a file server.
As mentioned in previous articles, 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.
Jekyll site will be available if something goes wrong with any of the nodes on our Docker Swarm Cluster. The data will be available to all the nodes in the cluster because of GlusterFS Replicated Volume.
I am going to create a folder jekyll-caddy
in /mnt
directory to upload _site
directory files to it.
cd /mnt
sudo mkdir -p jekyll-caddy
Tip
Upload files to Docker Swarm Cluster
I am using Windows 10 as Dev Environment and using the WinSCP tool to upload files to Docker Swarm Environment. (Upload the files to the Manager node and the files will be available throughout the cluster).
That’s it, you’re ready to use Jekyll on Windows 10 to develop sites.
Please download WinSCP using the below link if you are also using Windows 10 as your Dev Environment.
Those who use Linux as Dev Environment can use the scp command-line utility to upload files. Please find scp command
below for your reference.
scp local/file/path user@host:server/file/path
Caddy File Server Directory
Caddy’s static file server works by appending the requests URI path to the site’s root path. Requests to directories will be redirected to have a trailing forward slash, and requests to the files will be redirected to strip the trailing slash.
Please go through the below link to learn more about Caddy’s Static File Server directory.
Caddyfile – Jekyll
The Caddyfile is a convenient Caddy configuration format for humans.
Caddyfile is easy to write, easy to understand, and expressive enough for most use cases.
Production-ready Caddyfile for Jekyll as Static File Server. You can use it for other static site generators as well, like Hugo.
Learn more about Caddyfile here to get familiar with it.
{
email you@example.com
default_sni jekyll
cert_issuer acme
# Production acme directory
acme_ca https://acme-v02.api.letsencrypt.org/directory
# Staging acme directory
#acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
servers {
protocol {
experimental_http3
allow_h2c
strict_sni_host
}
timeouts {
read_body 10s
read_header 10s
write 10s
idle 2m
}
max_header_size 16384
}
}
jekyll.example.com {
log {
output file /var/log/caddy/jekyll.log {
roll_size 20mb
roll_keep 2
roll_keep_for 6h
}
format console
level error
}
root * /etc/caddy/html/jekyll.example.com
file_server {
hide .git
}
templates
try_files {path}.html {path}
encode gzip zstd
}
Please go to Caddy Post to get more insight to deploy it in the docker swarm cluster.
Caddy Docker Compose
Please find the full docker-compose file below. You can deploy as many sites as you want using it.
Don’t forget to map site data directories like
/mnt/jekyll-caddy:/etc/caddy/html/jekyll.example.com
in Caddy configurationcaddy.yml
.
I already wrote an article Caddy in Docker Swarm. Please go through if you want to learn more.
version: "3.7"
services:
caddy:
image: caddy:alpine
ports:
- "80:80"
- "443:443"
networks:
- caddy
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- /mnt/caddydata:/data
- /mnt/caddyconfig:/config
- /mnt/caddylogs:/var/log/caddy
- /mnt/jekyll-cadyy:/etc/caddy/html/jekyll.example.com
deploy:
placement:
constraints:
- node.role == manager
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
volumes:
caddydata:
driver: "local"
caddyconfig:
driver: "local"
caddylogs:
driver: "local"
jekyll-caddy:
driver: "local"
networks:
caddy:
external: true
Here I used the Official Caddy Alpine Docker Image. If you want to utilize custom DNS providers, I built a custom caddy docker container with plugins, like Cloudflare DNS, Caddy Auth Portal, etc…
Please find the custom caddy docker image below.
Deploy Caddy Stack using Docker Compose
Now it’s time to deploy our docker-compose file above, caddy.yml
using the below command
docker stack deploy --compose-file caddy.yml caddy
In the above command, you have to replace caddy.yml
with your docker-compose file name and caddy with whatever name you want to call this particular application
As mentioned earlier I named my docker-compose as caddy.yml
and named my application stack as caddy
Check the status of the stack by using docker stack ps caddy
Check caddy
stack logs using docker service logs caddy_caddy
One thing we observe is that it automatically re-directs to https
with Letsencrypt generated certificate. The information is stored in /data
directory.
I will be using this
caddy stack
as a reverse proxy / load balancer for the applications I am going to deploy to Docker Swarm Cluster.
Also I use docker network
caddy
to access the applications externally.
Access Jekyll Site
Now open any browser and type jekyll.example.com
to access the site. You will be greeted with the Jasper Theme-based Jekyll site with automatic HTTPS.
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… 🙄