Running Django on Docker: a workflow and code
Upcoming SlideShare
Loading in...5
×
 

Running Django on Docker: a workflow and code

on

  • 648 views

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

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

Statistics

Views

Total Views
648
Views on SlideShare
379
Embed Views
269

Actions

Likes
1
Downloads
1
Comments
0

2 Embeds 269

http://ixa.io 221
http://www.slideee.com 48

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Running Django on Docker: a workflow and code Running Django on Docker: a workflow and code Presentation Transcript

  • Running Django on Docker a workflow and code Alexey Kotlyarov • Danielle Madeley
  • The problem
  • A diverse world of applications
  • Reproducible deployments
  • Base OS (Debian bootstrap) App dependencies (Python, libs) Built application Transient runtime Immutable External Storage
  • But there's no standards! 12factor.net is a must read
  • Pallet An interface for Docker containers github.com/infoxchange/pallet
  • What's in deploy? database migrations loading fixtures install static content to static web server (CDN, Ceph, nginx, etc.)
  • What's in serve? Start app server Starting supporting services, e.g. Celery
  • Keep it lean
  • $ docker build .
  • Dockerfile FROM debian/ubuntu/fedora/etc. RUN apt-get -qq update && apt-get -qq install git mercurial python python-virtualenv python-pip ...
  • RUN useradd -d /app -r app WORKDIR /app
  • ADD requirements.txt /app/requirements.txt RUN virtualenv python_env && . python_env/bin/activate && pip install -r requirements.txt ADD . /app
  • VOLUME ["/static", "/storage"] RUN mkdir -p /static /storage && chown -R app /static /storage
  • RUN echo "__version__ = '`git describe`'" > myapp/__version__.py RUN ./invoke.sh install ENTRYPOINT ["./invoke.sh"] EXPOSE 8000
  • 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
  • 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:applicatio ;; *) ./manage.py "$@" ;; esac fi
  • Django settings.py
  • from dj_database_url import parse DATABASES = { 'default': parse(os.environ['DB_DEFAULT_URL']), }
  • # Logging is complex LOGGING['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, }
  • # Trust our nginx server USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', MY_SITE_DOMAIN = os.environ.get('SITE_DOMAIN') if MY_SITE_DOMAIN: ALLOWED_HOSTS = (MY_SITE_DOMAIN,)
  • IXDjango pallet configuration for Django pip install IXDjango from ixdjango.docker_settings import * github.com/infoxchange/ixdjango
  • An example (in Flask) github.com/danni/linux-conf-au-flask- tute/tree/dockerify
  • Running the container
  • docker run -p 8000:8000 -e DB_DEFAULT_URL=postgres://user:pass@db3:5432/mya -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
  • Urgh!
  • Forklift a tool for loading pallets github.com/infoxchange/docker-forklift
  • myapp/forklift.yaml services: - postgres - elasticsearch
  • $ forklift myapp serve
  • Developing with Forklift
  • $ forklift ./invoke.sh serve $ forklift ./manage.py test
  • Poking around inside containers (aka troubleshooting)
  • $ forklift --mount-root /tmp/myapp myapp sshd
  • Extending Forklift
  • 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 []
  • def environment(self): return { 'MEMCACHE_HOSTS': '|'.join(self.hosts), 'MEMCACHE_PREFIX': self.key_prefix, } def available(self): """ Check whether memcache is available """ ...
  • @classmethod def localhost(cls, application_id): """The default memcached provider""" return cls( key_prefix=application_id, hosts=['localhost:{0}'.format(cls.DEFAULT
  • @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.p )
  • Continuous integration
  • forklift --cleanroom myapp test
  • Legacy applications
  • Fin ;-P Questions? github.com/infoxchange/pallet github.com/infoxchange/docker-forklift