DjangoCon US—San Diego
Oct 2018
Deploying without Docker
Containerless Django
Peter Baumgartner
Slide 2
Slide 2 text
Founder at Lincoln Loop—lincolnloop.com
Former SysAdmin, DevOps for 8 years
Author of High Performance Django
About Me
Slide 3
Slide 3 text
Docker is cool!
Slide 4
Slide 4 text
@ipmb | #djangocon
Docker is cool!
The “pipeline”
Security
Isolation
Dev/prod parity
Slide 5
Slide 5 text
Just bundle the entire OS
Slide 6
Slide 6 text
Some philosophy
Slide 7
Slide 7 text
“
—Mike Perham
https://www.mikeperham.com/2016/02/09/kill-your-dependencies/
No code runs faster than no code.
No code has fewer bugs than no code.
No code uses less memory than no code.
No code is easier to understand than no code.
“
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
@ipmb | #djangocon
Docker Drawbacks
Slow
Extra abstractions
More software, more problems
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
How did we get here?
Slide 12
Slide 12 text
@ipmb | #djangocon
Deployments sucked
Dependencies would shift underneath you
Build tools and dev packages needed to be installed
Multiple languages, multiple builds (Python & Node)
Slide 13
Slide 13 text
@ipmb | #djangocon
The ideal deployment
Download a binary
Create a configuration file
Run it
@ipmb | #djangocon
Python isn’t C or Go
Requires a VM
Dynamic linking
Packaging isn’t straightforward
Slide 16
Slide 16 text
No content
Slide 17
Slide 17 text
Can we do better?
Slide 18
Slide 18 text
@ipmb | #djangocon
We already are!
Lock files via pipenv or poetry
Pre-compiled wheels (Pillow, psycopg2-binary, etc.)
Still lots of holes
- Assembling virtualenvs
- Static files
- Production webserver
@ipmb | #djangocon
ZIP applications?
Part of Python since 2.6
PEP-441 improves support in 3.5
Create a ZIP archive of your project. Run it
with Python.
…but no mechanism for handling
dependencies
Slide 21
Slide 21 text
No content
Slide 22
Slide 22 text
@ipmb | #djangocon
Enter shiv!
A project from LinkedIn
Zipapps with dependencies
A single artifact you can build → test → deploy
./myproject.pyz runserver
Slide 23
Slide 23 text
Django as a zipapp
Slide 24
Slide 24 text
Package your project with setup.py
Slide 25
Slide 25 text
@ipmb | #djangocon
Include templates & static files
Create a MANIFEST.in
graft your_project/collected_static
graft your_project/templates
Slide 26
Slide 26 text
@ipmb | #djangocon
Production webserver
gunicorn + whitenoise
⭐ https://pypi.org/project/django-pyuwsgi/
Slide 27
Slide 27 text
@ipmb | #djangocon
Build your zipapp
Slide 28
Slide 28 text
@ipmb | #djangocon
Run your zipapp
./yourproject.pyz pyuwsgi --http=:8000
Slide 29
Slide 29 text
@ipmb | #djangocon
Configuration
Same zipapp, but different settings per environment
Options:
- Multiple settings files and DJANGO_SETTINGS_MODULE
- Environment variables
- ⭐ https://pypi.org/project/goodconf/
Slide 30
Slide 30 text
@ipmb | #djangocon
The zipapp pipeline
Use CI (Travis, CircleCI, Bitbucket, etc.) to:
- Build
- Test
- Push
Deploy = Download and run
@ipmb | #djangocon
Isolation
You still need Python installed globally
Easy to install multiple Pythons on one server
Docker has better isolation, but do you need it?
Slide 37
Slide 37 text
@ipmb | #djangocon
What about parity?
Zipapp is the same from CI to all deployed
environments
Use Docker to mimic deployment
envionrment locally (or don't)
Slide 38
Slide 38 text
@ipmb | #djangocon
Pros
Simpler. No Docker on the server. No registry.
~1M fewer lines of code to depend on.
Smaller artifacts
Faster deployments
It's just Python
Slide 39
Slide 39 text
@ipmb | #djangocon
Cons
Not as isolated as true containers
Requires Python runtime on the server
Python-specific
Not cross-platform compatible (if you have
packages with C extensions)
Slide 40
Slide 40 text
@ipmb | #djangocon
Sweet spot for zipapps
You are deploying primarily Python services
You have outgrown PaaS (Heroku,
PythonAnywhere, Divio, etc.)
You have fewer than 50 services to maintain