Testing a Django app with Docker

[Permalink]     blog django docker proxama

I've been playing around with Docker a fair bit and recently hit upon a configuration that works nicely for me when testing code at work.

The basic premise is that I run a docker container that pretty well emulates the exact environment that the code will run in down to the OS so I don't need to care that I'm not running the same distribution as the servers we deploy to and that I can test my code at any time without having to rebuild the docker image.

Here's an annotated Dockerfile with the project-specific details removed.

# We start with ubuntu 14.04

FROM ubuntu:14.04
MAINTAINER Steve Engledow <steve@offend.me.uk>

USER root

# Install OS packages
# This list of packages is what gets installed by default
# on Amazon's Ubuntu 14.04 AMI plus python-virtualenv

 RUN apt-get update \
     && apt-get -y install software-properties-common git \
     ssh python-dev python-virtualenv libmysqlclient-dev \
     libqrencode-dev swig libssl-dev curl screen

# Configure custom apt repositories
# and install project-specific packages

COPY apt-key.list apt-repo.list apt.list /tmp/

# Not as nice as this could be as docker defaults to sh rather than bash
RUN while read key; do curl --silent "$key" | apt-key add -; done < /tmp/apt-key.list
RUN while read repo; do add-apt-repository -y "$repo"; done < /tmp/apt-repo.list
RUN apt-get -qq update
RUN while read package; do apt-get -qq -y install "$package"; done < /tmp/apt.list

# Now we create a normal user and switch to it

RUN useradd -s /bin/bash -m ubuntu \
    && chown -R ubuntu:ubuntu /home/ubuntu \
    && passwd -d ubuntu

USER ubuntu
WORKDIR /home/ubuntu
ENV HOME /home/ubuntu

# Set up a virtualenv andinstall python packages
# from the requirements file

COPY requirements.txt /tmp/

RUN mkdir .myenv \
    && virtualenv -p /usr/bin/python2.7 ~/.myenv \
    && . ~/.myenv/bin/activate \
    && pip install -r /tmp/requirements.txt \

# Set PYTHONPATH and activate the virtualenv in .bashrc

RUN echo "export PYTHONPATH=~/myapp/src" > .bashrc \
    && echo ". ~/.myenv/bin/activate" >> .bashrc

# Copy the entrypoint script

COPY entrypoint.sh /home/ubuntu/

EXPOSE 8000

ENTRYPOINT ["/bin/bash", "entrypoint.sh"]

And here's the entrypoint script that nicely wraps up running the django application:

#!/bin/bash

. ./.bashrc

cd myapp/src

./manage.py $*

You generate the base docker image from these files with docker build -t myapp ./.

Then, when you're ready to run a test suite, you need the following invocation:

docker run -ti --rm -P -v ~/code/myapp:/home/ubuntu/myapp myapp test

This mounts ~/code/myapp and /home/ubuntu/myapp within the Docker container meaning that you're running the exact code that you're working on from inside the container :)

I have an alias that expands that for me so I only need to type docked myapp test.

Obviously, you can substitute test for runserver, syncdb or whatever :)

This is all a bit rough and ready but it's working very well for me now and is repeatable enough that I can use more-or-less the same script for a number of different django projects.

  Just call me Anneka   blog code   Stony Silence   blog   When all the things went wrong   blog   Things   blog   Lessons learned   blog holiday   O Baggage Where Art Thou   blog holiday   All fired up   blog   Quayside   blog   tmux   blog linux   Simple mail transfer pondering   blog linux   Ramble   blog   Eligarf   blog   Laziness   blog   Netcat   blog linux   Judon't   blog   Things   blog   btw   blog c code   Stuff what I done   blog   Diet?   blog   TODO   blog   Shootah   code games games inactive   Tatil   blog holiday   Things we learned at the LUG meet   blog linux   MarkPoint   code command line desktop inactive other   Luck   blog   Yawn   blog   HBTM :)   blog code git   TODO   blog   Krobes   code games games inactive   Homophones   words   Non-euclidian pork scratching   blog   Lost at C   blog c code   JSTLV   code inactive other web   Ire   blog code   Ire   code command line inactive other   So, so dry   blog code   Gruff   code inactive other web   Things I've written recently   blog code   require("child_process");   blog   JZON   code inactive other web   Wyrm   code games games inactive   Picture Puzzle   code games games inactive   Zoomsite   code inactive other web   Rotate4   code games games inactive   Lines   code games games inactive   BreakIn   code games games inactive   nosef   code inactive javascript server server   Scary stuff   blog   Primes   blog   Hokey Cokey   blog   Web terminal lense book   blog   Strange lunch break   blog   Obfuna   code inactive other programming   Markdown   blog   ploxy   code command line inactive server server   miniserv   code command line inactive server server   Gnowt   code inactive other web   dmenu-notify   code desktop inactive other   Violining a contemptible fellow   blog code git   Break In!   blog games   xmodmap Hints and Tips   blog linux   Black Jack - pick up seven!   blog games   My favourite spoonerisms   words   Good things that have happened in the past week   blog   Good times with git   blog git   It's all Geek to me   blog   Javascript Closures   blog code javascript   Waffle. Move along.   blog   Things I learned today   blog   Hey, at least I'm not rioting   blog   HTML5 and holidays   blog holiday   Blah, cold. Do not want.   blog   Worst.Landlord.Ever   blog   Wheeee   blog   First!!1!one!!eleven   blog