Recently, I bought a new Macbook Pro for my development needs. Migrating my development environment from my old Fedora-based box turned out to be a nightmare, mostly because I’d installed stuff willy-nilly with no way to repeatably recreate it. I decided to do it the Right WayTM this time. I’ve worked with Vagrant before, but I decided to check out this Docker thing that the Hacker News crowd is going ga-ga over.
My app is fairly standard - a python flask app fronted by an nginx reverse-proxy that also serves static content.
I had the following (reasonable) requirements:
- Quick local development cycle: the code lives on my Macbook, and any changes to my code should auto restart the containerized app. No manual restarts required.
- Repeatable build process: I want to be able to recreate my dev environment on other machines and preferably use the same build process to deploy on cloud platforms like AWS, GCE or DigitalOcean.
With all the talk about Docker, I couldn’t find a simple step-by-step tutorial that shows you how to create such a setup, so here it is.
Docker best practices recommend one process per container, so we will need two containers 1, one each for nginx and your flask app. In practice, you will need a third database container, but for simplification, I have omitted it. Only the nginx container will be accessible to the outside world. The flask application container will only be accessible from the nginx container; in fact, it doesn’t even need network access. This process isolation is a major benefit touted by Docker.
The objective of this tutorial is to quickly get you up and running, so I don’t go into detail about what the various docker commands do. I will assume that you have already set up Docker on OS X as detailed here. I will also assume you have built a flask application before and have the code handy on your Mac. Let’s get started.
1. Create a Dockerfile for your Flask app
The nice thing about Docker images is that they’re extensible - you simply inherit most of the work that someone else has already done for you and add your stuff to it. There is an official debian-based Python image. However, I prefer running CentOS given that I’m familiar with the ecosystem, especially yum. I couldn’t find a CentOS 6 image with Python 2.7.8, so I created one here.
Now, let’s create a Dockerfile for your flask app using the CentOS python image as base. Create a file named
Dockerfile in your flask app’s root directory. I assume your app is called
app.py runs it.
All this does is copy your source directory into the container, install virtualenv and exposes the default flask port (more on this later).
2. Build Flask app image
From your flask app’s root directory, run this:
This creates a docker image named
3. Run Flask app container
This will run a container named
flaskapp based on the image we created in Step 2. The
-v flag will mount your local source directory inside the container, so your local changes will be reflected automatically.
4. Build nginx image
Given that nginx is a stable piece of software and I probably don’t need to muck around with a running nginx container, I just used the official Debian-based nginx image. We’ll create a
server block in the nginx config to proxy through to our flask app. Create a new directory (doesn’t matter where) and create the following
Now, create a file called flaskapp.conf in the same dir:
Now, build the nginx image as you did for the flask app:
5. Run nginx container
--link flag links the nginx container to the app container and exposes it as a host named with the link alias i.e
-p flag exposes port 80 of the container on port 8080 of your localhost (or boot2docker VM)
That’s it, we’re done! To access your app, find your boot2docker VM IP using
boot2docker ip and navigate to
http://$IP:8080 in your favorite browser.