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?