The build
script builds a Docker container, moshez/sayhello:<version>
.
$ ./build MY_VERSION
$ docker run --rm -it --publish 8080:8080 \
moshez/sayhello:MY_VERSION --port 8080
There will be a simple application running on port 8080.
If you own the domain name hello.example.com
, you can point it at a machine that the domain resolves to and then run:
$ docker run --rm -it --publish 443:443 \
moshez/sayhello:MY_VERSION --port le:/srv/www/certs:tcp:443 \
--empty-file /srv/www/certs/hello.example.com.pem
It will result in the same application running on a secure web site: https://hello.example.com
.
WSGI has been a successful standard. Very successful. It allows people to write Python applications using many frameworks (Django, Pyramid, Flask and Bottle, to name but a few) and deploy using many different servers (uwsgi, gunicorn and Apache).
Twisted makes a good WSGI container. Like Gunicorn, it is pure Python, simplifying deployment. Like Apache, it sports a production-grade web server that does not need a front end.
Modern web applications tend to be complex beasts. In order to be trusted by users, they need to have TLS support, signed by a trusted CA. They also need to transmit a lot of static resources --images, CSS and JavaScript files, even if all HTML is dynamically generated. Deploying them often requires complicated set-ups.
Container images allow us to package an application with all of its dependencies. They often cause a temptation to use those as the configuration management. However, Dockerfile is a challenging language to write big parts of the application in. People writing WSGI applications probably think Python is a good programming language. The more of the application logic is in Python, the easier it is for a WSGI-based team to master it.
Pex is a way to package several Python "distributions" (sometimes informally called "Packages", the things that are hosted by PyPI) into one file, optionally with an entry-point so that running the file will call a pre-defined function. It can take an explicit list of wheels but can also, as in our example here, take arguments compatible with the ones pip takes. The best practice is to give it a list of wheels, and build the wheels with pip wheel
.
The pkg_resources module allows access to files packaged in a distribution in a way that is agnostic to how the distribution was deployed. Specifically, it is possible to install a distribution as a zipped directory, instead of unpacking it into site-packages
. The code:pex format relies on this feature of Python, so adherence to using pkg_resources
to access data files is important in order to not break code:pex compatibility.
Let's Encrypt is a free, automated, and open Certificate Authority. It has invented the ACME protocol in order to make getting secure certificates a simple operation. txacme is an implementation of an ACME client, i.e., something that asks for certificates, for Twisted applications. It uses the server endpoint plugin mechanism in order to allow any application that builds a listening endpoint to support ACME.
The twist
command-line tools allows running any Twisted service plugin. Service plugins allow us to configure a service using Python, a pretty nifty language, while still allowing specific customizations at the point of use via command line parameters.
Our setup.py
files defines a distribution called sayhello
. In it, we have three parts:
src/sayhello/wsgi.py
: A simple Flask-based WSGI applicationsrc/sayhello/data/index.html
: an HTML file meant to serve as the rootsrc/twisted/plugins/sayhello.py
: A Twist plugin
There is also some build infrastructure:
build
is a Python script to run the build.build.docker
is a Dockerfile designed to build pex files, but not run as a production server.run.docker
is a Dockerfile designed for production container.
Note that build does not push the resulting container to DockerHub.
Glyph Lefkowitz has inspired me in his blog about how to build efficient containers. He has also spoken about how deploying applications should be no more than one file copy.
Tristan Seligmann has written txacme.
Amber "Hawkowl" Brown has written "twist", which is much better at running Twisted-based services than the older "twistd".
Of course, all mistakes and problems here are completely my responsibility.