It is always good to simplify things. The last post Continuous Blogging - Migrating to Docker Cloud was not really finished, and I had promised to optimize the “continuous deployment” aspect.
After finishing a blog post and pushing it to the repo, I still had to manually create Docker images. Only after pushing them to the registry were they deployed automatically to production. Not really “Continuous Deployment” style.
My goal was: after saving, committing, and pushing a new blog post to the repo, everything should be automated so the post lands directly on a system for proofreading—like a staging or user-acceptance environment.
After proofreading, if everything is fine, the whole thing should travel to production with a simple git command.
This is the final workflow after committing the post:
git push origin master
That’s all. After a few seconds I get notified in my Slack channel that a new image has been deployed to my Docker Cloud. Then I proofread under a subdomain called preview and when I am confident I only set and push a tag:
git tag -f prod
git push -f --tags
Then, again, wait a little for the Slack notification. Finally, everything can be read under the www subdomain.
I accomplished this with two additional steps:
- Modifying my Docker image for Jekyll.
- Adding automated build jobs to Docker Cloud.
The biggest difference was not using Nginx any longer and instead using Jekyll’s built-in webserver to serve the blog. Therefore I was able to have only one Docker image for building and serving the content.
FROM jekyll/jekyll:3.4.0
MAINTAINER Cool Guy "guy@cool.com"
RUN gem install jekyll-gist therubyracer json --no-doc --no-ri
ADD. /srv/jekyll
CMD ["jekyll", "serve"]
This Dockerfile is picked up by the build server whenever there is a push to the Git repo (e.g., GitHub or Bitbucket).
The configuration of the build jobs is simple: I map Git tags to corresponding Docker tags.

After the Docker image is built, it will automatically be redeployed to the Docker host.
The trick is to set the corresponding service to autoredeploy: true:
lb-prod:
image: myloadbalancer:latest
autorestart: always
autoredeploy: true
links:
- myblog-prod
- myblog-preview
ports:
- "80:80"
roles:
- global
myblog-prod:
image: myblog:prod
autorestart: always
autoredeploy: true
myblog-preview:
image: myblog:latest
autorestart: always
autoredeploy: true
That is all. Much simpler now to get a new post online.
Only one thing left: local preview and debugging. Simple!
One short docker-compose.yml and a docker-compose up later, the blog can be viewed locally on port 4000.
version: '2'
services:
jekyll:
build:
context:.
dockerfile: DOCKERFILE
Done for today!