Slide 1

Slide 1 text

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

Slide 14

Slide 14 text

@ipmb | #djangocon The ideal deployment /usr/local/bin/traefik \
 --configFile=/etc/traefik/traefik.toml /usr/local/bin/telegraf \
 --config=/etc/telegraf/telegraf.conf /usr/sbin/nginx -c /etc/nginx/nginx.conf

Slide 15

Slide 15 text

@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

Slide 19

Slide 19 text

@ipmb | #djangocon Prior art Private PyPI virtualenv-clone Platter dh-virtualenv Pex

Slide 20

Slide 20 text

@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

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

What about security?

Slide 33

Slide 33 text

Systemd's got your back

Slide 34

Slide 34 text

@ipmb | #djangocon Systemd is awesome ProtectSystem=strict
 ProtectHome=true DynamicUser=true CapabilityBoundingSet=~CAP_SYS_ADMIN AppArmorProfile=srv.yourproject.pyz ProtectKernelTunables=true
 ProtectControlGroups=true
 ProtectKernelModules=true
 PrivateDevices=true
 PrivateTmp=true
 SystemCallArchitectures=native

Slide 35

Slide 35 text

What about isolation?

Slide 36

Slide 36 text

@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

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Thanks! Peter Baumgartner [email protected] @ipmb