1 of 42

What Django Deployment

Is Really About

James Walters

2 of 42

3 of 42

Is Django Hard to Deploy?

🤔️

James Walters - james.walters.click

4 of 42

The Penguin in the Room

James Walters - james.walters.click

5 of 42

Four Main Concerns

  1. Static Files
  2. Database
  3. WSGI Server
  4. Web Server

(and a couple of other things)

James Walters - james.walters.click

6 of 42

Static Files 📁️

James Walters - james.walters.click

7 of 42

But {% static %}, right?

James Walters - james.walters.click

8 of 42

index.html

about.html

news.html

posts.html

www.yourwebsite.com

Apache / nginx

James Walters - james.walters.click

9 of 42

template.html

www.yourwebsite.com

Apache / nginx

Database

Django

James Walters - james.walters.click

10 of 42

template.html

www.yourwebsite.com

Apache / nginx

Database

Django

style.css

STATIC_ROOT

script.js

. . .

James Walters - james.walters.click

11 of 42

Static Files

  • Once you deploy, the production web server needs to handle this.
  • Once you’ve set STATIC_ROOT, you have to run manage.py collectstatic to actually collect your static files inside the STATIC_ROOT directory.
    • You have to do this whenever you add or change any of your static files.

James Walters - james.walters.click

  • Django actually has been handling static files for you in development, because manage.py runserver is the only web server available.

12 of 42

But Whitenoise, right?

  • It’s great for situations where you can’t directly configure your web server
  • Also, excels when serving your site from CDNs–automatically handles these HTTP headers for you!
    • The cache-busting that Whitenoise can do for you is a real plus if you rely some JS running client-side to handle any core functionality
  • Whitenoise is a middleware that intercepts the request and serves up the static file, skipping the rest of Django’s (comparatively) slow request cycle

James Walters - james.walters.click

13 of 42

But Whitenoise, right?

  • If you have access to your web server, consider writing an nginx/Apache config–it’s not that hard!
  • You made a web app–shouldn’t you understand how a web server works? 🤔️

James Walters - james.walters.click

https://realpython.com/django-nginx-gunicorn/#serving-static-files-directly-with-nginx

14 of 42

What about user uploaded files?

  • Whitenoise won’t work here
  • Eventually you’d probably want to set up a third party storage backend, like an Amazon S3 bucket, for user uploads.
  • Similar process, but use MEDIA_ROOT / MEDIA_URL instead of STATIC_ROOT / STATIC_URL in settings.py (see Django documentation)

James Walters - james.walters.click

15 of 42

Database 💾️

James Walters - james.walters.click

16 of 42

But SQLite, right?

  • In deployment, SQLite may not be suitable (though it's more capable than you're often led to believe)
  • Generally if you're using some sort of cloud provider, you'll be connecting to a remote database that's managed for you.

James Walters - james.walters.click

https://www.youtube.com/watch?v=yTicYJDT1zE

17 of 42

But SQLite, right?

  • This probably won’t be different for your app in any material way–the important difference will be that you'll need to configure connection details in your settings.py.
  • SQLite keeps everything in one single file. Since you don't "connect" to it, you don't have to handle connection details. Your DATABASE section in settings.py is pretty simple.

James Walters - james.walters.click

18 of 42

settings.py

DATABASES = {

"default": {

"ENGINE": "django.db.backends.sqlite3",

"NAME": "mydatabase",

}

}

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.postgresql'

'NAME': 'mydatabase',

'USER': 'mydatabaseuser',

'PASSWORD': 'mypassword',

'HOST': '127.0.0.1',

'PORT': '5432',

}

}

James Walters - james.walters.click

19 of 42

Database

  • The point here is not to compare databases and tell you which one to choose–the point is to show that your database situation will almost certainly be different in deployment, and you need to be aware of that.
  • Once you’ve got your connection details set up, you’ll want to run manage.py migrate to set up your database for the first time.

James Walters - james.walters.click

20 of 42

WSGI Server 🥃️

James Walters - james.walters.click

21 of 42

But manage.py runserver, right?

James Walters - james.walters.click

22 of 42

www.yourwebsite.com

Apache / nginx

Django

James Walters - james.walters.click

23 of 42

www.yourwebsite.com

Apache / nginx

Django

WSGI

Server

Gunicorn

Waitress

uWSGI

wsgi.py

James Walters - james.walters.click

24 of 42

Web Server 🕸️

James Walters - james.walters.click

25 of 42

Web Server

  • Apache and nginx are your two main options, both are great.
  • RealPython has a good article on how to configure a Django project to use gunicorn through nginx.

James Walters - james.walters.click

https://realpython.com/django-nginx-gunicorn/

26 of 42

But do you even need to configure the web server yourself? 🤔️

It depends on your deployment choice…

James Walters - james.walters.click

27 of 42

VPS

  • Examples include: Linode, Digital Ocean
  • It'll be a very manual setup process, with little hand holding. But, you'll understand every step of the way.
  • If you go this route, you'll be responsible for everything about the server: restarting it if it goes down, tracking and rotating log files, managing security settings and updates, etc.
  • A virtual private server (VPS) is a virtual machine running in the cloud.

James Walters - james.walters.click

28 of 42

PaaS

  • Examples include: Heroku, PythonAnywhere, DigitalOcean, Fly.io
  • The provider will abstract away the underlying computer, and you just focus on your app.
  • You get your code uploaded, provide some details about hooking up a database, static files, where the script to execute is, etc.
  • You don't have to worry about the server-y stuff like worrying about updates, checking logs, understanding security settings, or configuring the web server.
  • A platform-as-a-service (PaaS) is kind of different.

James Walters - james.walters.click

29 of 42

(Soft) Verdict?

James Walters - james.walters.click

✅️ PaaS

30 of 42

James Walters - james.walters.click

31 of 42

Django's Deployment Checklist ✅️

James Walters - james.walters.click

32 of 42

Django’s Deployment Checklist

  • For example, it will warn you if DEBUG = True.
  • To use it, just run manage.py check --deploy
  • Django has a handy built-in automated tool that will look over your settings file and point out any settings with values that aren’t appropriate for deployment.

James Walters - james.walters.click

33 of 42

manage.py check --deploy

$ python manage.py check --deploy

System check identified some issues:

WARNINGS:

?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.

?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.

?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' indicating that it was generated automatically by Django. Please generate a long and random value, otherwise many of Django's security-critical features will be vulnerable to attack.

?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.

?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.

?: (security.W018) You should not have DEBUG set to True in deployment.

?: (security.W020) ALLOWED_HOSTS must not be empty in deployment.

James Walters - james.walters.click

34 of 42

django-simple-deploy 😃️

James Walters - james.walters.click

35 of 42

django-simple-deploy

  • From Eric Matthes, author of Python Crash Course
  • Aims to be a utility that you can run against your code, and it will automatically handle all the steps needed to get your code deployed.

James Walters - james.walters.click

https://django-simple-deploy.readthedocs.io/en/latest/

36 of 42

django-simple-deploy

  • Helps a newcomer get their code online, then they can compare the changes it made to their code settings and learn how exactly it went about it.
  • Currently supports deploying to Fly.io, Platform.sh, and Heroku. More platforms should be on the way.

James Walters - james.walters.click

https://django-simple-deploy.readthedocs.io/en/latest/

37 of 42

django-production 🏭️

James Walters - james.walters.click

38 of 42

django-production

  • From Peter Baumgartner at Lincoln Loop
  • Aims to provide sane defaults for getting your Django project into a production deployment setting

James Walters - james.walters.click

https://github.com/lincolnloop/django-production

39 of 42

django-production

  • whitenoise - for serving static files
  • django-environ - for reading settings from environment variables
  • django-webserver[gunicorn] - for running the webserver via manage.py
  • django-alive - for a health check endpoint at /-/alive/

James Walters - james.walters.click

https://github.com/lincolnloop/django-production

From README:

40 of 42

The Whale in the Room

41 of 42

Docker Pros

Docker Cons

  • Isolate application environments
    • No more “well it works on my machine”
  • This means you can deploy multiple apps to the same machine
  • Streamline deployment
    • docker run
    • docker-compose up
  • Adds some complexity�
  • You still have to know everything we’ve talked about

42 of 42

Wrapping Up 🎁️

See my blog james.walters.click for links to these slides, and the resources mentioned.

Github: github.com/iamjameswalters

Mastodon: @jameswalters@fosstodon.org

Email: jameswalters@hey.com

Thank You!