parente.dev

This is My Blog on Docker + IPython

July 13, 2014

Late last year, I decided to refresh my blog with a more responsive design. In doing so, I looked for ways to simplify my blogofile setup. I looked at Wintersmith, Pelican, and PyGreen but in the end decided to roll my own: five Mako templates, 170 lines of Python, and my posts in Markdown. I was pleased. Mostly. Two aspects of my generator nagged me, both of which I corrected this past weekend.

Dockerize It

First, my simple script had not-so-simple dependencies: the Mako, Markdown, and Pygments Python packages; a local webserver to preview the rendered site; and rsync to upload the generated site to my webhost. Originally, I setup my local box with all of these, choosing to "pay-later" should I get a new computer, have to restore my box, want to post from another machine, etc. Now eight months on, I decided to pay-down this technical debt by creating a Docker image that packages everything together using a simple Dockerfile:

FROM ubuntu:14.04

MAINTAINER Peter Parente <parente@cs.unc.edu>

RUN apt-get update
RUN apt-get -yq install python-pip openssh-client rsync
RUN pip install Mako==0.9.1 Markdown==2.4 Pygments==1.6

ADD . /srv/blog
WORKDIR /srv/blog

I drive the build and use of the image from a convenient Makefile in my blog git repo.

# build the docker image once
make build

# render my blog posts acessbile via a contiainer-host mount
# then run a Python SimpleHTTPServer to view the results locally
make render

# render and rsync the content to my webhost
make publish

Now rendering, previewing, and uploading my blog requires Docker and, optionally, make. That's it.

IPythonize It

Second, I felt both liberated and limited by Markdown-only postings. I say liberated because writing in Markdown beat the heck out of writing pure HTML or using some WYSIWYG editor, especially for postings laden with code. I say limited because I missed the richness of explanation available in another tool I'd been using daily for over a year now, IPython Notebook. To quiesce the latter feeling, I decided to jump on the bandwagon and support both pure Markdown files and IPython Notebooks as blog posts.

The addition of a couple dependencies in my Dockerfile, the ballooning of my generator code to a massive 250 lines of Python, and the creation of a new template and stylesheet enabled the blog post you see before you.

And now, an amazing demonstration of IPython-powered posts ...

HOWTO: xkcd matplotlib plots

First, install the Humor Sans font.

In [1]:
!wget http://antiyawn.com/uploads/Humor-Sans-1.0.ttf -O ~/.fonts/Humor\ Sans.ttf
--2014-07-14 02:00:41--  http://antiyawn.com/uploads/Humor-Sans-1.0.ttf
Resolving antiyawn.com (antiyawn.com)... 72.167.131.154
Connecting to antiyawn.com (antiyawn.com)|72.167.131.154|:80... 
connected.
HTTP request sent, awaiting response... 
200 OK
Length: 25832 (25K) [text/plain]
Saving to: ‘/root/.fonts/Humor Sans.ttf’

0% [ ] 0 --.-K/s 
100%[======================================>] 25,832       136KB/s   in 0.2s

2014-07-14 02:00:41 (136 KB/s) - ‘/root/.fonts/Humor Sans.ttf’ saved [25832/25832]

Next, flush the matplotlib font cache.

In [2]:
!rm ~/.cache/matplotlib/fontList.cache

Then, enable inline plots in the style of xkcd.

In [3]:
%matplotlib inline
In [4]:
import matplotlib.pyplot as plt
plt.ioff()
In [5]:
plt.xkcd()
Out[5]:
<matplotlib.rc_context at 0x7f39fe924d90>

Finally, humbly copy and tweak an existing matplotlib example.

In [6]:
fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(1, 1, 1)
ax.bar([-0.125, 1.0-0.125], [0, 1], 0.25)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.set_xticks([0, 1])
ax.set_xlim([-0.5, 1.5])
ax.set_ylim([0, 2])
ax.set_xticklabels(['Before IPython support', 'After IPython support'])
plt.yticks([0, 1, 2])

plt.title("Useless plots on this blog")

Out[6]:
<matplotlib.text.Text at 0x7f39fe8340d0>

And voilá!

In [7]:
plt.show()
No description has been provided for this image

The future is bright, I tell you.

Genericize It

So I've scratched my two blog itches, and, as expected from itching, have created more. The fact that my blog generator is now in a portable, reusable container yet still somewhat hardcoded to this site bugs me. With a bit more elbow grease, I believe I can make a Docker image that can seed a blog like mine for any purpose simply by setting a few environment variables.

When or whether I get around to scratching this itch is an open question. Meanwhile, I solemnly promise never to write another veribified heading on this blog (but I refuse to make a similar promise for xkcd-style plots).

Another Read: Run a Docker Registry Backed by IBM SoftLayer Object Storage »

A Docker registry stores the images and the graph for a set of repositories. The shiny, new Docker Hub uses one to store all of the wonderful repositories created by the Docker community. You too can run a registry by spinning up an instance of the official Docker registry image. In fact, it's trivial to get a registry running using host local disk: