130 likes | 237 Views
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.
E N D
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 • Kickstart Install • Base Image • Configuration Management • Puppet, Chef • Packaging Systems
What Python? • Database? • Backup / Restore • Failover • Performance • Caching? • HTTP • Objects • Queuing? • SSL? Application Environment
It’s just code, right? • Probably Not Application
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 • Just use pip! • Not so fast. • Lots of external dependencies • Eliminate them with a local cache • Don’t’ forget virtualenv! Dependencies
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.pyrunserver • settings.py • No logic allowed! • “unknown” import times • Critical • Local_settings.py • More of the same • Consider pushing configuration in externally via environ, configparser, etc Configuration
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): deftest_fixture_applied(): self.assertEquals(Poll.objects.get(q=‘test q’) • Fixtures. Consider writing them in Python! • Testable • More resilient to change • Less pkpain • Migrations! • Test them Database
management/__init__.py: from django.db.models.signals import post_syncdb from south.signals import post_migrate from .. import models, fixtures defupdate_poll_fixtures(verbose=True): fixtures.poll.apply() if verbose: print "Updating dynamic fixtures for profile” defupdate_fixtures_post_syncdb(sender, **kwargs): update_poll_fixtures() defupdate_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 • Fabric? • RPM? • Tar? • Git? • Rsync? • Update Stuff • syncdb • apply fixtures • Test Green! • Flip/Flop Blue/Green • (Roll back to Blue) App App Deploy / Test Data Deployment: Blue/Green
Erik LaBianca, WiserTogether, Inc. erik.labianca@gmail.com @easel https://linkedin.com/in/eriklabianca/ https://slideshare.net/easel1/ https://github.com/easel/ https://github.com/WiserTogether/ Questions?