This article will teach you how to:
- Automatically build your Jekyll site into a docker-container using Docker Cloud. Including:
- serve a Jekyll site using nginx inside a container
- build your
_site
static site on Docker Cloud - test to verify that your build was successful
Note: For info on setting up a Jekyll site, please refer to the Jekyll docs.
For the purpose of this article we will assume the following conventions:
- docker username:
myusername
- docker container that we are building:
mycontainer
Packaging your Jekyll site for productiong
In your standard Jekyll website, add a Dockerfile
:
FROM nginx:stable
ADD ./_site /usr/share/nginx/html
This is pretty simple:
- We use the standard
nginx
public container. - We
ADD
the contents of_site
to the default static content folder inside the nginx container (/usr/share/nginx/html
).
Now, to get this to work locally you would run the following commands:
jekyll build
-> create site static contentsdocker build -t myusername/mycontainer:latest
-> build our containerdocker push myusername/mycontainer:latest
-> push it to the hub.
But since we're using Docker Cloud, it would be better if this could happen via an Automated Build (note: setting up Automated builds is beyond the scope of this article).
To set up an automated build in docker cloud, we would typically:
- connect our Github repo to docker cloud
- add some build rules (such as whenever I push to
master
, kick off a build) - sit back and enjoy the magical container building.
However: there's a problem. We don't want to have to manually build _site
, and we especially don't want to have to include it in our git repo. But: the Automated build only runs our Dockerfile
.. and our Dockerfile
assumes that _site
exists.
We need some way to build _site
on Docker's infrastructure as part of our automated build. So:
Build your site on docker cloud using build hooks
Build hooks to the rescue!
Docker build hooks allow you to run commands at various points in the Automated build life-cycle.
The following build hooks exist:
hooks/post_checkout
hooks/pre_build
hooks/post_build
hooks/pre_test
hooks/post_test
hooks/pre_push (only used when executing a build rule or automated build )
hooks/post_push (only used when executing a build rule or automated build )
So, in our root directory, we need to create: hooks/pre_build
, and then we'll use the the official Jekyll image to build our site:
hooks/pre_build:
#!/bin/bash
echo "=> Build the site using jekyll"
mkdir -p _site
docker run --volume=`pwd`:/srv/jekyll jekyll/jekyll jekyll build
What's happening here:
- We're using the
jekyll/jekyll
(which will give us a Jekyll ready environment) - We map our current directory to
/srv/jekyll
(where the Jekyll image expects the Jekyll site to be - We build our site by running
jekyll build
Notes:
- You need to create the
_site
directory manually (line 3:mkdir -p _site
) otherwise you will get a permissions error:
Generating...
jekyll 3.4.3 | Error: Permission denied @ dir_s_mkdir - /srv/jekyll/_site
pre_build hook failed! (1)
ERROR: Build failed: pre_build hook failed! (1)
Test that Jekyll build works.
It is possible that we make a commit which has a mistake in it that causes the Jekyll build to fail. This would result in us having a broken container image. Which is bad. So: Automated tests to the rescue!
In our root directory, let's create a docker-compose.test.yml
file which will run a Jekyll build. If the build succeeds, we're all good:
docker-compose.sut.yml
sut:
image: jekyll/jekyll
command: jekyll build
And that's it. Now we have magical Docker CI all sorted. When we push to master the following process is kicked off:
- Push to master
- Docker Cloud kicks off an automated build
- It picks up our pre_build hook and using that builds the static resources that are our Jekyll site
- Build our website container using our
Dockerfile
- Test that our build actually works without error
- Push our image and make it available.
\o/