If you’re working on a Python application in Django and you’re wondering how can Docker make your life a bit easier, then you’ve come to the right place.
Given Docker’s omnipresence across various operating systems, it’s crazy not to use something that gives you a consistent development and deployment experience. The old days of wondering why it works or doesn’t work just on your machine should be gone.
Ever heard this in your office?
- “just recreate the virtualenv”
- “it works on my machine”
- “can’t run the project on my “
- “the project broke my computer”
Docker is a fast-moving target and there are many competing tools, features, and ways of solving problems. Let’s just say it’s hard to find a “minimalist 2018 docker project template for Django”.
Using a custom build system two years ago seemed like a good idea, but now that Docker has multi-stage builds it’s just a bunch of code that you can easily avoid maintaining. Template systems for generating docker-compose.yml also seemed like a good idea, but then you realize yaml is a complex and tricky language and it’s better to just use Docker Compose’s support for multiple configuration files.
That being said, here‘s a template grown out of past projects and experiments.
Why should you use it?
Why is it different than all the other 99999 project skeletons out there for Django and Docker? What are the trade-offs?
-
No custom build system.
We use multi stage builds and docker-compose with a base image to avoid some of the caching problems, but not all (individual python package dependencies will not be cached – if you change one dependency then all the dependencies are built again).
-
No running anything outside Docker.
Everything goes through a container, thus behavior will be consistent across environments. That means no manage.py or setup.py to mislead you into trying to run stuff out of a container.
.
-
No fancy volume tricks while keeping the single service per container rule.
While we could have a separate nginx container to serve static files and proxy to an uwsgi container we just make uwsgi serve static files to avoid using shared volumes and other Docker configuration shenanigans. This means uwsgi configuration is slightly heavier.
.
-
No configuration templating or generation for docker-compose.yml.
We keep things simple and avoid the crazy issues that happen when you load and save yaml. Unfortunately, yaml is a complicated language and figuring out how to keep ordering and formatting, and with which yaml library is a wild-goose chase.
.
-
Error early and clearly.
Here are some examples:
-
- A missing .env would make the build fail instead of leaving you wondering why the project misbehaves (broken settings).
- Incorrectly trying to use ./test.sh would give a clear error message instead of leaving you wondering what –something: command not found means.
- Broken service dependencies are handled early. If pg didn’t start the web will give an error at startup instead of leaving you wondering why your view giving a weird error about transactions.
.
-
Sensible defaults.
PostgreSQL, Redis, and Celery containers are included but the configuration is very light if not just the default. Test runner is pytest. Experts can easily swap out to MySQL, RabbitMQ or unittest.
.
-
Development problems sorted out.
- There’s a test.sh for testing so you always get a reliable and clean test environment.
- There’s a reloader container so you don’t have to manually restart Celery all day long.
- Development-specific docker-compose configuration with few common tweaks (like smaller worker pool or more permissive security settings) and volume configuration sorted out so you don’t have to rebuild the containers all day long.
The overarching theme is pragmatic minimalism – for running/deploying you should not need anything more than docker-compose but development needs to be palatable (the said pragmatism). When you start simple it’s easy to extend and tune the project to your specific needs. If you start with a heavy layout and tooling you’ll end up wasting time on shoehorning, or end up in the loony bin 🙂
Final thoughts
Hopefully, you’re now convinced to try this template – if this doesn’t get you started with Django and Docker, nothing does. Just kidding. Give it a try, see how it works, and report issues. Pull requests are welcomed.