Django Deployment Best Practices

Download Report

Transcript Django Deployment Best Practices

Django Deployment
{
Tips, Tricks and Best Practices
Erik LaBianca, WiserTogether, Inc.

You mission, should you choose to accept it:



Make your application run with 1 click,
everywhere it counts, every time.
Make your application run exactly the same way,
everywhere it counts, every time.
Prove that the above are true.
Reproducibility



Reproducible Infrastructure
Reproducible Systems
Reproducible [Django] Applications




Dependencies
Configuration
Data
Deployment
Steps to Reproducibility

Systems: Virtual or Physical




Power Management
Console
Backup / Restore
Network Layer



Load Balancing
Security
Performance
Infrastructure

A Stable Foundation


Stable Operating System
Reproducible Installation



Configuration Management


Kickstart Install
Base Image
Puppet, Chef
Packaging
Systems


What Python?
Database?




Caching?




Backup / Restore
Failover
Performance
HTTP
Objects
Queuing?
SSL?
Application Environment

It’s just code, right?

Probably Not
Application


Just use pip!
Not so fast.



Lots of external
dependencies
Eliminate them
with a local
cache
Don’t’ forget
virtualenv!
lib/pypi-cache:
Django-1.4.3.tar.gz
requirements.txt:
Django==1.4.3
Type this:
pip install --no-index --find-links
file://$(PWD)/lib/pypi-cache -r
requirements.txt
Dependencies

settings.py




Local_settings.py


No logic allowed!
“unknown”
import times
Critical
More of the same
Consider pushing
configuration in
externally via
environ,
configparser, etc
settings.py:
from urlparse import urljoin
from os import environ
import dj_database_url #courtesy of Heroku
DATABASES =
dj_database.config(default=“xxx”)
BASE_URL = environ[‘DJANGO_BASE_URL’]
STATIC_URL = urljoin(BASE_URL, ‘static’)
MEDIA_URL = urljoin(BASE_URL, ‘media’)
Run this:
DJANGO_BASE_URL=http://cdn.com/base/
django-admin.py runserver
Configuration

Fixtures. Consider
writing them in
Python!




Testable
More resilient to
change
Less pk pain
Migrations!

fixtures/polls.py:
from ..models import Poll, Choice
def apply():
p = Poll.objects.get_or_create(q=‘test q’,
defaults=dict(pub_date=‘1980-01-01))
c1 = Choices.objects.get_or_create(poll=p,
choice_text=‘option 1’)
fixtures/tests/test_poll.py:
Class PollFixtureTestCase(TestCase):
def test_fixture_applied():
self.assertEquals(Poll.objects.get(q=‘test q’)
Test them
Database
management/__init__.py:
from django.db.models.signals import post_syncdb
from south.signals import post_migrate
from .. import models, fixtures
def update_poll_fixtures(verbose=True):
fixtures.poll.apply()
if verbose:
print "Updating dynamic fixtures for profile”
def update_fixtures_post_syncdb(sender, **kwargs):
update_poll_fixtures()
def update_fixtures_post_migrate(app, **kwargs):
if app == ’polls':
update_poll_fixtures()
post_syncdb.connect(fixtures_post_syncdb, sender=models)
post_migrate.connect(fixtures_post_migrate)
Interwebs


Back Up Everything!
Move files to Green






Update Stuff





Fabric?
RPM?
Tar?
Git?
Rsync?
App
App
Deploy / Test
syncdb
apply fixtures
Test Green!
Flip/Flop Blue/Green
(Roll back to Blue)
Data
Deployment: Blue/Green
Erik LaBianca, WiserTogether, Inc.
[email protected]
@easel
https://linkedin.com/in/eriklabianca/
https://slideshare.net/easel1/
https://github.com/easel/
https://github.com/WiserTogether/
Questions?