LiveReload Development with Django, Docker, Circus, and Chaussette

UPDATE: I got it to work.

Use inotify on your host machine to watch the directory for changes and run docker exec <container> circusctl restart <circus_process>

And since MAC doesn't have inotify, we can use fswatch.

brew install fswatch

Then we can watch a directory like this. It will print any changes to the console.

fswatch -vro . | xargs -I{} docker exec grouper circusctl restart grouper

TLDR: I didn't get it to work.

I thought it would be nice to develop on the same environment that I use in production.

My production setup is:

  • Nginx docker container for the web server
  • Redis docker container for Celery queue
  • Django docker container for the app
  • Circus process manager
  • Chaussette WSGI server process
  • Celery queueing process

It's not good/secure to run python manage.py runserver in a production environment, hence the Chaussette WSGI.

My docker-compose.yml file makes my deploy as simple as:

  • git pull
  • docker-compose up

And I can run that on a fresh OS install (imaged with docker of course).

I ran into several problems with this setup though, one of which is live-reloading.

As I modify my Django app files, I want the server to automatically pick up those changes and restart.

I thought I could use inotify to listen for changes to any file in the directory and write a custom plugin for circus.

There is currently a plugin that does something very similar that I tried to use as a base (CommandReloader), but modifying it to listen to all files in a directory was more difficult than modifying it to listen to a single file that I could specify in my circus.ini config, and then having circus run a bash script any time THAT specific file changed.

I could then use a shell script (https://gist.github.com/eihli/7cc96c21e74cc48c2f82c93b8044a375#file-onchange-sh) that used inotify to run touch restart any time a file changed. Circus would watch restart and restart the Chaussette server.

But... after all that work I realized restarting Chaussette would not cause the Django wsgi.application to be reloaded.

On top of that, inotify does not work when mounting volumes to docker containers.

And what about debugging with pdb.set_trace? Good question. There's epdb. But that's got a whole new set of problems when trying to use that with docker and multiple processes from Circus.

Cheers to successfully finding a way it doesn't work. Back to the drawing board.