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

Like this? Share it with your network

Share

Running Django on Docker: a workflow and code

  • 1,975 views
Uploaded on

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.

More in: Software
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,975
On Slideshare
1,412
From Embeds
563
Number of Embeds
4

Actions

Shares
Downloads
8
Comments
0
Likes
3

Embeds 563

http://ixa.io 302
https://ixa.io 197
http://www.slideee.com 63
http://www.slidesearchengine.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Running Django on Docker a workflow and code Alexey Kotlyarov • Danielle Madeley
  • 2. The problem
  • 3. A diverse world of applications
  • 4. Reproducible deployments
  • 5. Base OS (Debian bootstrap) App dependencies (Python, libs) Built application Transient runtime Immutable External Storage
  • 6. But there's no standards! 12factor.net is a must read
  • 7. Pallet An interface for Docker containers github.com/infoxchange/pallet
  • 8. What's in deploy? database migrations loading fixtures install static content to static web server (CDN, Ceph, nginx, etc.)
  • 9. What's in serve? Start app server Starting supporting services, e.g. Celery
  • 10. Keep it lean
  • 11. $ docker build .
  • 12. Dockerfile FROM debian/ubuntu/fedora/etc. RUN apt-get -qq update && apt-get -qq install git mercurial python python-virtualenv python-pip ...
  • 13. RUN useradd -d /app -r app WORKDIR /app
  • 14. ADD requirements.txt /app/requirements.txt RUN virtualenv python_env && . python_env/bin/activate && pip install -r requirements.txt ADD . /app
  • 15. VOLUME ["/static", "/storage"] RUN mkdir -p /static /storage && chown -R app /static /storage
  • 16. RUN echo "__version__ = '`git describe`'" > myapp/__version__.py RUN ./invoke.sh install ENTRYPOINT ["./invoke.sh"] EXPOSE 8000
  • 17. 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
  • 18. 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
  • 19. Django settings.py
  • 20. from dj_database_url import parse DATABASES = { 'default': parse(os.environ['DB_DEFAULT_URL']), }
  • 21. # 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, }
  • 22. # 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,)
  • 23. IXDjango pallet configuration for Django pip install IXDjango from ixdjango.docker_settings import * github.com/infoxchange/ixdjango
  • 24. An example (in Flask) github.com/danni/linux-conf-au-flask- tute/tree/dockerify
  • 25. Running the container
  • 26. 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
  • 27. Urgh!
  • 28. Forklift a tool for loading pallets github.com/infoxchange/docker-forklift
  • 29. myapp/forklift.yaml services: - postgres - elasticsearch
  • 30. $ forklift myapp serve
  • 31. Developing with Forklift
  • 32. $ forklift ./invoke.sh serve $ forklift ./manage.py test
  • 33. Poking around inside containers (aka troubleshooting)
  • 34. $ forklift --mount-root /tmp/myapp myapp sshd
  • 35. Extending Forklift
  • 36. 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 []
  • 37. def environment(self): return { 'MEMCACHE_HOSTS': '|'.join(self.hosts), 'MEMCACHE_PREFIX': self.key_prefix, } def available(self): """ Check whether memcache is available """ ...
  • 38. @classmethod def localhost(cls, application_id): """The default memcached provider""" return cls( key_prefix=application_id, hosts=['localhost:{0}'.format(cls.DEFAULT
  • 39. @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 )
  • 40. Continuous integration
  • 41. forklift --cleanroom myapp test
  • 42. Legacy applications
  • 43. Fin ;-P Questions? github.com/infoxchange/pallet github.com/infoxchange/docker-forklift