47

Running Django on Docker: a workflow and code

Embed Size (px)

DESCRIPTION

An introduction to Pallet and Forklift, a standard and tool for deploying and developing web applications on top of Docker.

Citation preview

Page 1: Running Django on Docker: a workflow and code

Running Djangoon Dockera workflow and code

Alexey Kotlyarov • Danielle Madeley

Page 2: Running Django on Docker: a workflow and code

The problem

Page 3: Running Django on Docker: a workflow and code
Page 4: Running Django on Docker: a workflow and code
Page 5: Running Django on Docker: a workflow and code

A diverse world ofapplications

Page 6: Running Django on Docker: a workflow and code

Reproducibledeployments

Page 7: Running Django on Docker: a workflow and code
Page 8: Running Django on Docker: a workflow and code
Page 9: Running Django on Docker: a workflow and code

Base OS (Debian bootstrap)

App dependencies(Python, libs)

Built application

Transient runtime

Imm

utab

leExternalStorage

Page 10: Running Django on Docker: a workflow and code

But there's nostandards!

12factor.net is a must read

Page 11: Running Django on Docker: a workflow and code

PalletAn interface forDocker containers

github.com/infoxchange/pallet

Page 12: Running Django on Docker: a workflow and code

What's in deploy?database migrationsloading fixturesinstall static content to static web server(CDN, Ceph, nginx, etc.)

Page 13: Running Django on Docker: a workflow and code

What's in serve?Start app serverStarting supporting services, e.g. Celery

Page 14: Running Django on Docker: a workflow and code

Keep it lean

Page 15: Running Django on Docker: a workflow and code

$ docker build .

Page 16: Running Django on Docker: a workflow and code

DockerfileFROM debian/ubuntu/fedora/etc.RUN apt-get -qq update && apt-get -qq install \ git mercurial \ python python-virtualenv python-pip \ ...

Page 17: Running Django on Docker: a workflow and code

RUN useradd -d /app -r appWORKDIR /app

Page 18: Running Django on Docker: a workflow and code

ADD requirements.txt /app/requirements.txtRUN virtualenv python_env && \ . python_env/bin/activate && \ pip install -r requirements.txt

ADD . /app

Page 19: Running Django on Docker: a workflow and code

VOLUME ["/static", "/storage"]

RUN mkdir -p /static /storage && \ chown -R app /static /storage

Page 20: Running Django on Docker: a workflow and code

RUN echo "__version__ = 'git describe'" \ > myapp/__version__.py

RUN ./invoke.sh install

ENTRYPOINT ["./invoke.sh"]

EXPOSE 8000

Page 21: Running Django on Docker: a workflow and code

invoke.sh#!/bin/sh

# default parameters: ${APP_USER:=app}: ${WEB_CONCURRENCY:=1}export WEB_CONCURRENCY

if [ "x$(whoami)" != "x$APP_USER" ]; then # ensure we own our storage chown -R "$APP_USER" /static /storage

# Call back into ourselves as the app user exec sudo -sE -u "$APP_USER" -- "$0" "$@"else

Page 22: Running Django on Docker: a workflow and code

else . ./startenv case "$1" in deploy) shift 1 # consume command from $@ ./manage.py migrate "$@" ;;

serve) gunicorn -w "$WEB_CONCURRENCY" \ -b 0.0.0.0:8000 "${APP}.wsgi:application" ;;

*) ./manage.py "$@" ;; esacfi

Page 23: Running Django on Docker: a workflow and code

Django settings.py

Page 24: Running Django on Docker: a workflow and code

from dj_database_url import parseDATABASES = { 'default': parse(os.environ['DB_DEFAULT_URL']),}

Page 25: Running Django on Docker: a workflow and code

# Logging is complexLOGGING['handlers']['logstash'] = { 'level': 'DEBUG' if DEBUG else 'INFO', 'class': 'logging.handlers.SysLogHandler', 'address': (os.environ['SYSLOG_SERVER'], int(os.environ['SYSLOG_PORT'])) 'socktype': socket.SOCK_STREAM \ if os.environ['SYSLOG_PROTO'] == else socket.SOCK_DGRAM,}

Page 26: Running Django on Docker: a workflow and code

# Trust our nginx serverUSE_X_FORWARDED_HOST = TrueSECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', MY_SITE_DOMAIN = os.environ.get('SITE_DOMAIN')if MY_SITE_DOMAIN: ALLOWED_HOSTS = (MY_SITE_DOMAIN,)

Page 27: Running Django on Docker: a workflow and code

IXDjangopallet configuration forDjangopip install IXDjango

from ixdjango.docker_settings import *

github.com/infoxchange/ixdjango

Page 28: Running Django on Docker: a workflow and code

An example(in Flask)

github.com/danni/linux-conf-au-flask-tute/tree/dockerify

Page 29: Running Django on Docker: a workflow and code

Running thecontainer

Page 30: Running Django on Docker: a workflow and code

docker run \ -p 8000:8000 \ -e DB_DEFAULT_URL=postgres://user:pass@db3:5432/myapp \ -e SITE_DOMAIN=myapp-staging.company.com \ -e SITE_PROTO=https \ -e ENVIRONMENT=staging \ -e ELASTICSEARCH_URLS=http://elastic-1:9200/myapp \ -v /mnt/docker-storage/myapp:/storage \ -h WHY_ARE_YOU_STILL_READING_THIS \ myapp \ serve

Page 31: Running Django on Docker: a workflow and code

Urgh!

Page 32: Running Django on Docker: a workflow and code

Forklifta tool for loading pallets

github.com/infoxchange/docker-forklift

Page 33: Running Django on Docker: a workflow and code

myapp/forklift.yamlservices:- postgres- elasticsearch

Page 34: Running Django on Docker: a workflow and code

$ forklift myapp serve

Page 35: Running Django on Docker: a workflow and code

Developing withForklift

Page 36: Running Django on Docker: a workflow and code

$ forklift ./invoke.sh serve$ forklift ./manage.py test

Page 37: Running Django on Docker: a workflow and code

Poking aroundinside containers

(aka troubleshooting)

Page 38: Running Django on Docker: a workflow and code

$ forklift --mount-root/tmp/myapp myapp sshd

Page 39: Running Django on Docker: a workflow and code

Extending Forklift

Page 40: Running Django on Docker: a workflow and code

forklift.services.memcache@register('memcache')class Memcache(Service):

providers = ('localhost', 'container')

DEFAULT_PORT = 11211

def __init__(self, key_prefix='', hosts=None):

self.key_prefix = key_prefix self.hosts = hosts or []

Page 41: Running Django on Docker: a workflow and code

def environment(self):

return { 'MEMCACHE_HOSTS': '|'.join(self.hosts), 'MEMCACHE_PREFIX': self.key_prefix, }

def available(self): """ Check whether memcache is available """

...

Page 42: Running Django on Docker: a workflow and code

@classmethod def localhost(cls, application_id): """The default memcached provider"""

return cls( key_prefix=application_id, hosts=['localhost:{0}'.format(cls.DEFAULT_PORT)])

Page 43: Running Django on Docker: a workflow and code

@classmethod @transient_provider def container(cls, application_id): """Memcached provided by a container."""

container = ensure_container( image='fedora/memcached', port=cls.DEFAULT_PORT, application_id=application_id, )

return cls( key_prefix=application_id, hosts=['localhost:{0}'.format(container.port)], )

Page 44: Running Django on Docker: a workflow and code

Continuousintegration

Page 45: Running Django on Docker: a workflow and code

forklift --cleanroom myapp test

Page 46: Running Django on Docker: a workflow and code

Legacyapplications

Page 47: Running Django on Docker: a workflow and code

Fin ;-PQuestions?

github.com/infoxchange/palletgithub.com/infoxchange/docker-forklift