This website was generated using Pelican!
More interestingly, it is hosted using Docker <http://docker.com/>_! You can take a look at the Repo on GitHub to get all the details, scripts and Dockerfiles used, but I will provide here a short summary of the idea behind this approach.
There are 4 containers that make this website running:
- Pelican (Git + SSH + Pelican)
- Nginx HTTP Server
- Reverse HTTP Proxy
Pelican (Git + SSH + Pelican)
The pelican container is responsible for building this static website. It provides a Git repository via an SSH connection (by deriving from the debian-git-ssh image). The Git repository is enhanced with a post-receive hook, that forces the generation of the website and its deployment.
This process is very generic, and any other tool for static site generation could be used instead of Pelican. The way I link to think about this container is as a simple service that takes in input a Git repository and outputs a website. This point of view is driven by the fact that the container does not store any data. Instead, we use a data container to do make data persistent. This has the advantage that we can re-build, modify, remove the pelican container without loosing data.
A data container is a container that exports some volumes. The image website-data exports two volumes: /git and /www. The pelican container will have access to both volumes, handle the repo stored in the /git volume and output the generate site in /www.
Ideally, one could design a backup container that takes volumes in input and makes backups using S3 or other cloud provider... This will probably stay in my TODO list for a while :)
Nignx HTTP Server
In order to publish the static website, I use a rather standard nginx installation. The main difference is that linking volumes accross containers requires them to have the same name (i.e., you cannot link /www to /var/html/www). Therefore, I extended the nginx basic Dockerfile, and created a sym-link between the volume and the directory where nginx looks for the website.
One of the advantages of this design is the possibility of instantiating multiple servers that have access to the same data-container. This makes it possible to experiment with different webservers, or perform A/B testing.
To avoid having to change DNS entries for each subdomain, I am using the nginx reverse proxy image jwilder/nginx-proxy . This is a really nice trick, in which the reverse-proxy configuration file is automatically (re-)generated everytime a new container is started with the environment variables VHOST_HOST. Each time I start a new webserver container, I just need to specify a different vhost name, and the reverse proxy will be automatically setup.
More details are available in the original author's blog post.
I had been wanting to experiment with this idea of micro-services for a while. Although, this design is far from perfect, I think it fits nicely into (my?) understanding of micro services: highly specialized components that are interchangeable and non-persistent.