Using Drone to Build and Deploy a Jekyll Site
In this blog post I show you how Drone can be used to automatically build and deploy a Jekyll site. Drone is a very lightweight CI/CD platform which uses Docker containers to execute pipelines which are defined in simple YAML configuration files. The configuration shown in this post is also used for building and deploying this blog when changes are pushed to the corresponding repository. Let’s start by looking at a simple pipeline configuration for a Jekyll site.
Pipeline Configuration
To define the pipeline which should be executed by Drone, a file named .drone.yml
has to be created in the root of the project repository.
This file contains configuration parameters and code for each stage of the pipeline.
Build Stage
We start with a simple stage for building the site.
In this stage, the standard ruby Docker image is used and two commands are executed in the root directory of the project.
bundle install
installs the necessary ruby gems and bundle exec jekyll build
builds the site using the Jekyll gem.
The pipeline is executed when commits are pushed to the master branch of the repository.
pipeline:
build:
image: ruby
commands:
- bundle install
- bundle exec jekyll build
branches: master
Deploy Stage
To deploy the site built in the previous stage, we define a second stage which copies the generated _site
directory to a server with rsync
.
For this, we use the Drone plugin drillster/drone-rsync.
We specify some parameters like the target host, the user or the source and target directory.
In this configuration, the plugin uses public key authentication, where the corresponding private key is defined by a Drone secret.
Details of how to specify the private key secret can be seen in the plugin documentation.
deploy:
image: drillster/drone-rsync
hosts: [ "lafl-server.florian-latifi.at" ]
user: blog
source: _site
target: /var/www/blog/
recursive: true
delete: true
secrets: [ plugin_key ]
Notify Stage
Finally, we want to be notified when the pipeline execution succeeds or something fails during execution. Here, we use the Drone plugin drillster/drone-email. This plugin allows to send emails to a given address through a specified SMTP host. We define parameters for the SMTP host and port and the FROM mail address.
notify:
image: drillster/drone-email
host: lafl-server.florian-latifi.at
port: 25
from: Drone <drone@lafl-server.florian-latifi.at>
when:
status: [ failure, success ]
Caching Gems Installed by Bundler
To speed up builds, we want to cache gems installed by bundler during the build stage instead of re-installing them each time the pipeline is executed. In recent Drone versions, caching is handled by Drone plugins which have to be used in specific pipeline stages. Here, we use the Drone plugin drillster/drone-volume-cache. This plugin allows to cache directories in Docker volumes on the Docker host. Note that for the plugin to be able to create volumes, the trusted flag has to be set in the project repository settings of Drone.
Adjusting Build Stage
The cache plugin is only able to cache directories residing in the Drone workspace directory which is /drone
.
However, the ruby image used in the build stage stores gems installed by bundler in /usr/local/bundle
.
Therefore, the BUNDLE_PATH
environment variable has to be adjusted in the build stage such that bundler installs gems in a directory residing in /drone
.
For this, we choose the directory /drone/.bundle
.
The adjusted build stage looks as follows.
build:
image: ruby
environment:
- BUNDLE_PATH=/drone/.bundle
commands:
- bundle install
- bundle exec jekyll build
Stage for Restoring the Cache
Before the build stage is executed, a stage is needed for restoring the cached directory out of the Docker volume.
In the following, the configuration for this stage is shown where the cache plugin is configured accordingly.
We define a volume by specifying a directory path on the Docker host, i.e. /tmp/bundle-cache
, which is mounted in a directory path on the Docker container created during pipeline execution, i.e. /cache
.
The plugin is configured such that it copies the content of /cache
to /drone/.bundle
.
restore-cache:
image: drillster/drone-volume-cache
restore: true
mount:
- /drone/.bundle
volumes:
- /tmp/bundle-cache:/cache
Stage for Rebuilding the Cache
After the build stage is executed, a stage is needed for rebuilding the cached directory in the Docker volume.
In the following, the configuration for this stage is shown where the cache plugin is configured accordingly.
We define the same volume as shown in the previous stage and configure the plugin such that it copies the content of /drone/.bundle
back to /cache
.
rebuild-cache:
image: drillster/drone-volume-cache
rebuild: true
mount:
- /drone/.bundle
volumes:
- /tmp/bundle-cache:/cache
Final Pipeline Configuration
This is how the final pipeline configuration looks like.
pipeline:
restore-cache:
image: drillster/drone-volume-cache
restore: true
mount:
- /drone/.bundle
volumes:
- jekyll-blog-cache:/cache
build:
image: ruby
environment:
- BUNDLE_PATH=/drone/.bundle
commands:
- bundle install
- bundle exec jekyll build
rebuild-cache:
image: drillster/drone-volume-cache
rebuild: true
mount:
- /drone/.bundle
volumes:
- jekyll-blog-cache:/cache
deploy:
image: drillster/drone-rsync
hosts: [ "lafl-server.florian-latifi.at" ]
user: blog
source: _site
target: /var/www/blog/
recursive: true
delete: true
secrets: [ plugin_key ]
notify:
image: drillster/drone-email
host: lafl-server.florian-latifi.at
port: 25
from: Drone <drone@lafl-server.florian-latifi.at>
when:
status: [ failure, success ]
branches: master
Conclusion
In this blog post I showed you how Drone can be used to automatically build and deploy a Jekyll site. We defined a pipeline configuration with stages for building the site, as well as deploying the generated files to a remote server. The pipeline configuration also contained a stage for notifying the developer via email when the pipeline execution succeeded or something failed during execution. Finally, to speed up builds we defined additional stages for caching the directory into which bundler installed gems are stored using a Docker volume.
Click here if you want to check out the source of my Jekyll blog where this pipeline configuration is also used.
I like Drone a lot, because it’s very easy to set up on a server, lightweight in resource usage and can be integrated with many different repository hosting software such as Github or Gitea. Furthermore, it’s highly extensible via plugins and the configuration of pipelines is also very simple. Therefore, I can highly recommend you to try it out.
I hope you liked this blog post. If you have any feedback or question regarding this topic, please leave a comment in the comments section below. Stay tuned for upcoming posts.
Comments