The Problem With Your Dockerized Django Development Workflow
Are you using docker-compose to bring up your local Django development environment? Did you experience the following nuisances lately?
- You had to rebuild a Docker image.
- You had to wait forever for your Django container to come up.
- You were waiting while a container was spinning up or down to continue with your work.
- You had to restart the whole container stack.
- You ran containerized management commands, which took way longer than they should.
Did you feel like your flow was being interrupted? Isn’t it frustrating?
But it’s also really cool! Otherwise, you would have ditched Docker by now, right?
- Your stack needs less resources than a Vagrant-powered VM would.
- You can get your whole development stack up with a single command.
- You have reproducible, automated environments which are easily tested and versioned.
- You can develop on both Mac and Linux machines, without much additional work or clutter!
Can You Do Better?
You can. Let’s go through and what you can do to make your dockerized development workflows better.
Don’t Rebuild Your Docker Images Often.
You shouldn’t have to rebuild Docker images on a daily basis while developing locally. That should only be necessary, if required system packages have changed or you’re starting from scratch on a fresh machine.
- Do you mount your code via a volume into the container, instead of ADDing it to the image?
Your Containers Should Come Up Without Doing (Much) Heavy Lifting.
The first time you bring up your development stack, it’s acceptable to wait for the content of your pip requirements files to be installed for the first time. But afterwards, you should not have to wait for much longer than a few seconds.
- Do you cache your virtualenv content in a volume, so you don’t have to install everything when a container starts?
Use Exec For Management Commands.
If your docker-compose stack is running, you don’t really have to use something like:
$ docker-compose -f local.yml run --rm django python manage.py migrate
You can use exec instead, so you don’t have to start a new container and get results without additional waiting times.
Don’t Manipulate Your Django Development Server With The Complete Docker-Compose Stack.
Do you really want to wait for all of your backing services to restart, when you want to restart your development server? This kinda works most of the time, but there are better ways.
- Have you looked into commands to stop and bring up single services, instead of the whole stack?
I prefer to go one step further. You can run a sleep command as the entry point of your app container, then exec into it. This way, the container keeps running, but you can start or stop the development server (and run management commands) without having to touch the rest of the stack.
Or, even better, you can…
Run a Docker-Compose Stack for Backing Services, But Develop Your App Locally.
This one might seem a bit controversial, but it’s a very good thing to do. You run databases and other services, which you’re not actively developing, in containers, and get all benefits from using Docker, but have complete control over your app. Just because you’re using Docker, does not mean you have to use it for everything you could.
This method can make for very smooth, IDE-friendly development workflows, without having to go through dependency-hell.
- Consider forwarding backing service ports to the host, and develop your app outside of a container.
With Django, you can use virtualenv and don’t need many system-specific packages to make it work.
If you’re frustrated from delays and waiting times with your dockerized Django development environment, you might have some fixable issues.
Working with Docker does not have to be painful and slow. You can get the portability and setup convenience of using containers, and still enjoy smooth workflows.
Take a look at the way you’re working with your dockerized Django app right now. Did any of the issues sound familiar? You can do better, and improve your day-to-day dev experience by a lot!
Look into the approaches described above, and get rid of annoying waiting times :)