SlideShare a Scribd company logo
Copyright 2019 © systemati.co
Docker and Django
Meet For A Tango
Hendrik Frentrup

hendrik@systemati.co

15 July 2019

London, UK
Copyright 2019 © systemati.co
Ways to get in touch
hendrik@systemati.co

@HendrikFrentrup

linkedin.com/in/frentrup/

github.com/hendrikfrentrup

medium.com/@hendrik.frentrup
Copyright 2019 © systemati.co
Links
•GitHub repo for the code

•github.com/hendrikfrentrup/docker-django

•Walkthrough:

•medium.com/devopslinks/tech-edition-how-to-dockerize-a-django-web-
app-elegantly-924c0b83575d

•https://medium.com/@hendrik.frentrup/tech-edition-django-dockerization-
with-bells-and-whistles-and-a-tad-bit-of-cleverness-2b5d1b57e289

•Further reading:

•medium.com/panaseer-labs-engineering-data-science/how-devops-
helped-us-solve-our-big-data-development-problem-263474dfeedb

•Contact details:

•Email: hendrik@systemati.co

•Twitter: @hendrikfrentrup
•LinkedIn: linkedin.com/in/frentrup/
Copyright 2019 © systemati.co
Code!
• This will be a pretty detailed walk-through

• There will be a lot of code in detail

• Sometimes I’ll flick through things pretty quickly

• I’ll make the slides available
Copyright 2019 © systemati.co
The Problem
• Moving code from development environments to staging or
production can break things

• The state of environments drifts and is hard to manage

• For lack of access, developers have no insight into the specifics of
production environments
Copyright 2019 © systemati.co
Why?
• Ease the pain of moving from Dev to Prod

• Step towards being Cloud Native

• Twelve Factor App (https://12factor.net/)

• Infrastructure-as-Code

• Productivity
Copyright 2019 © systemati.co
From here
Application
Database
Local machine
Copyright 2019 © systemati.co
To here
Docker
web
gunicorn
server
db
postgres
Local machine
db-admin
pgadmin
server
nginx
nginx
server
python
manage.py
runserver
*.conf
+ static/
pg-data/
Copyright 2019 © systemati.co
• Move a locally running app into a container

• Setup database, admin and nginx services

• Run migrations

• Logging
• Implement Infrastructure-as-code

• Bring development and production
environments close together

• Increase productivity & working collaboratively
Outline
Copyright 2019 © systemati.co
Simple app running locally
python manage.py runserver
db.sqlite3
Local machine
Copyright 2019 © systemati.co
10 commands to set up
> git init
> git checkout -b develop
> virtualenv env
> source env/bin/activate
> pip install Django>=2.1
> echo 'Django>=2.1' >> requirements.txt
> django-admin startproject my-site
> git add * && git commit -m "..."
> python mysite/manage.py runserver
Copyright 2019 © systemati.co
App running in container
Docker
web
python manage.py runserver
db.sqlite3
Local machine
Copyright 2019 © systemati.co
App inside Docker
> touch Dockerfile
> docker build -t django-docker:0.0.1 .
> docker run -p 8001:8001 docker-django:0.0.1
______Dockerfile____________________________________________________________
FROM python:3.6.7-alpine
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD ./ /code/
RUN pip install -r requirements.txt
CMD ["python", "mysite/manage.py", "runserver", "0.0.0.0:8001"]
Copyright 2019 © systemati.co
Success looks like …
Copyright 2019 © systemati.co
Local storage
Docker
web
python manage.py runserver
db.sqlite3db.sqlite3
Local machine
Copyright 2019 © systemati.co
Moving to docker-compose
> touch docker-compose.yml
> docker-compose up
______docker-compose.yml__________________________________________________
version: "3"
services:
web:
build: .
command: python mysite/manage.py runserver 8001
ports:
- “8001:8001”
volumes:
- ./mysite/:/code
maps ports and container code/db to local filesystem
Copyright 2019 © systemati.co
Database service
Docker
web
python
manage.py
runserver
db
postgres
Local machine
Copyright 2019 © systemati.co
Adding a database service
______docker-compose.yml__________________________________________________
version: "3"
services:
web:
build: .
command: python mysite/manage.py runserver 8001
ports:
- “8001:8001”
volumes:
- ./mysite/:/code
db:
image: postgres
networks:
- backend
networks:
backend:
driver: bridge
Copyright 2019 © systemati.co
Handling env. variables
______settings.py____________________________________________________________
POSTGRES_PASSWORD = os.environ.get('POSTGRES_PASSWORD')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': POSTGRES_PASSWORD,
'HOST': ‘db',
'PORT': '5432',
},
______.env__________________________________________________________________
POSTGRES_PASSWORD=secret
POSTGRES_USER=postgres
DJANGO_SECRET_KEY=secret
> touch .env
> echo 'psycopg2-binary' >> requirements.txt
Copyright 2019 © systemati.co
Credentials in envvars
______docker-compose.yml__________________________________________________
version: "3"
services:
web:
[...]
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_USER: ${POSTGRES_USER}
db:
[...]
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_USER: ${POSTGRES_USER}
Copyright 2019 © systemati.co
Rebuilding the web image
______Dockerfile____________________________________________________________
FROM python:3.6.7-alpine
ENV PYTHONUNBUFFERED 1
RUN apk update && 
apk add --virtual build-deps gcc python-dev musl-dev && 
apk add postgresql-dev
RUN mkdir /code
WORKDIR /code
ADD ./ /code/
RUN pip install -r requirements.txt
Copyright 2019 © systemati.co
A bit of admin
> docker-compose exec web python mysite/manage.py migrate
> docker-compose exec web python mysite/manage.py createsuperuser
Run that every time we tear down our containers?

Note down the credentials we’ve used?
Copyright 2019 © systemati.co
Data migrations
______0001_initial.py___________________________________________________________
import os
from django.db import migrations
class Migration(migrations.Migration):
dependencies = []
def generate_superuser(apps, schema_editor):
from django.contrib.auth.models import User
DJANGO_SU_NAME = os.environ.get('DJANGO_SU_NAME')
DJANGO_SU_EMAIL = os.environ.get('DJANGO_SU_EMAIL')
DJANGO_SU_PASSWORD = os.environ.get('DJANGO_SU_PASSWORD')
superuser = User.objects.create_superuser(
username=DJANGO_SU_NAME, email=DJANGO_SU_EMAIL,
password=DJANGO_SU_PASSWORD)
superuser.save()
operations = [
migrations.RunPython(generate_superuser),
]
Copyright 2019 © systemati.co
More credentials
______docker-compose.yml__________________________________________________
version: "3"
services:
web:
[...]
environment:
DJANGO_DB_NAME: ${DJANGO_DB_NAME}
DJANGO_SU_NAME: ${DJANGO_SU_NAME}
DJANGO_SU_EMAIL: ${DJANGO_SU_EMAIL}
DJANGO_SU_PASSWORD: ${DJANGO_SU_PASSWORD}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_USER: ${POSTGRES_USER}
Copyright 2019 © systemati.co
web, db and admin services
Docker
web
python
manage.py
runserver
db
postgres
Local machine
db-admin
pgadmin server
Copyright 2019 © systemati.co
Adding a DB admin service
______docker-compose.yml__________________________________________________
[...]
db-admin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
depends_on:
- db
ports:
- "8080:80"
networks:
- backend
[...]
Copyright 2019 © systemati.co
pgadmin in action
Copyright 2019 © systemati.co
Local app for debugging
Docker
web
python
manage.py
runserver
db
postgres
Local machine
db-admin
pgadmin
server
python
manage.py
runserver
Copyright 2019 © systemati.co
Run a local app alongside
______settings.py____________________________________________________________
from decouple import config
SECRET_KEY = config(‘DJANGO_SECRET_KEY')
DEBUG = config('DJANGO_DEBUG', default=False, cast=bool)
WEB_HOST = config('DJANGO_WEB_HOST', default='localhost')
DB_HOST = config('DJANGO_DB_HOST', default='localhost')
DB_NAME = config(‘DJANGO_DB_NAME’)
[...]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': POSTGRES_USER,
'PASSWORD': POSTGRES_PASSWORD,
'HOST': DB_HOST,
'PORT': '5432',
},
Copyright 2019 © systemati.co
Run a local app alongside
______docker-compose.yml_____________________________________
[...]
environment:
DJANGO_DEBUG: "True"
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY}
DJANGO_DB_HOST: “db"
[...]
Copyright 2019 © systemati.co
With nginx
Docker
web
gunicorn
server
db
postgres
Local machine
db-admin
pgadmin
server
nginx
nginx
server
python
manage.py
runserver
Copyright 2019 © systemati.co
Add nginx server
______default.conf_______________________________
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web:8001;
}
}
______settings.py________________________________
[...]
ALLOWED_HOSTS = [WEB_HOST, ‘localhost']
[...]
> echo “gunicorn” >> requirements.txt
Copyright 2019 © systemati.co
Add nginx server
______docker-compose.yml__________________________________________________
[...]
web:
command: gunicorn mysite.wsgi --bind 0.0.0.0:8001
[...]
nginx:
image: nginx:latest
ports:
- 8088:80
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- backend
depends_on:
- web
[...]
Copyright 2019 © systemati.co
Static files & persistent data
Docker
web
gunicorn
server
db
postgres
Local machine
db-admin
pgadmin
server
nginx
nginx
server
python
manage.py
runserver
*.conf
+ static/
pg-data/
Copyright 2019 © systemati.co
Serving static assets
______settings.py_______________________________________
[...]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
> python mysite/manage.py collectstatic
______default.conf_____________________
server {
[...]
location /static {
alias /code/static;
}
}
Copyright 2019 © systemati.co
Serving static assets
______docker-compose.yml__________________________________________________
[...]
nginx:
[...]
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./mysite/static:/code/static
[...]
db:
volumes:
- ./postgres-data:/var/lib/postgresql/data
[...]
Copyright 2019 © systemati.co
Mapped ports
Docker
web
8001
db
5432
Local machine
db-admin
8080
nginx
8088
8000
Copyright 2019 © systemati.co
Splitting YAML files
______docker-compose.override.yml_____________
[...]
volumes:
- ./mysite:/code
environment:
DJANGO_DEBUG: “True"
[...]
______docker-compose.yml_______________
[...]
web:
build: .
command: gunicorn mysite.wsgi
--bind 0.0.0.0:8001
depends_on:
- db
networks:
- backend
[...]
Copyright 2019 © systemati.co
Logs
Copyright 2019 © systemati.co
Logging locally
• To STDOUT!
Copyright 2019 © systemati.co
Logs in shared envs
• Complex topic and no one size fits all

• Log aggregator (SumoLogic, Splunk, ELK etc.)

• A complete ELK stack in one container

• Various logging driver options

• Fluentd

• Gelf
Log aggregatorFluentd
LogStash
ElasticSearch
Kibana
Copyright 2019 © systemati.co
Logging
Local machine
Staging environment
Build
server
Log aggregator
Production
Code
repo
Local machine
push
trigger
tail
deploy
stream
deploy
stream
Copyright 2019 © systemati.co
That’s all!
Thanks

More Related Content

PDF
Building Twitter's SDKs for Android
PDF
Mobile Performance Testing Crash Course
PPTX
Physical web
PDF
Java REST API Framework Comparison - PWX 2021
PDF
Mobile Development with Ionic, React Native, and JHipster - ACGNJ Java Users ...
PDF
Google Play Services Rock
PDF
Front End Development for Backend Developers - GIDS 2019
PPTX
How to make your Money Machine with Internet of Things
Building Twitter's SDKs for Android
Mobile Performance Testing Crash Course
Physical web
Java REST API Framework Comparison - PWX 2021
Mobile Development with Ionic, React Native, and JHipster - ACGNJ Java Users ...
Google Play Services Rock
Front End Development for Backend Developers - GIDS 2019
How to make your Money Machine with Internet of Things

What's hot (19)

PPTX
GIT, RVM, FIRST HEROKU APP
PDF
Introduction to Android Wear
PDF
Front End Development for Back End Java Developers - Jfokus 2020
PDF
Bootiful Development with Spring Boot and React - UberConf 2018
PDF
Bootiful Development with Spring Boot and React - SpringOne 2017
PDF
Front End Development for Back End Java Developers - NYJavaSIG 2019
PDF
A Gentle Introduction to Angular Schematics - Angular SF 2019
PDF
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
PPT
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
PDF
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
PDF
Teaching Your WAF New Tricks
PDF
Bootiful Development with Spring Boot and React - RWX 2017
PDF
Hybrid Apps (Native + Web) via QtWebKit
PDF
Advanced Mac Software Deployment and Configuration: Just Make It Work!
PDF
JAX-RS JavaOne Hyderabad, India 2011
PDF
Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019
PDF
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
PPT
Os Johnson
PDF
Spark IT 2011 - Developing RESTful Web services with JAX-RS
GIT, RVM, FIRST HEROKU APP
Introduction to Android Wear
Front End Development for Back End Java Developers - Jfokus 2020
Bootiful Development with Spring Boot and React - UberConf 2018
Bootiful Development with Spring Boot and React - SpringOne 2017
Front End Development for Back End Java Developers - NYJavaSIG 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
Microservices for the Masses with Spring Boot, JHipster, and OAuth - Utah JUG...
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Teaching Your WAF New Tricks
Bootiful Development with Spring Boot and React - RWX 2017
Hybrid Apps (Native + Web) via QtWebKit
Advanced Mac Software Deployment and Configuration: Just Make It Work!
JAX-RS JavaOne Hyderabad, India 2011
Spring Boot APIs and Angular Apps: Get Hip with JHipster! KCDC 2019
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
Os Johnson
Spark IT 2011 - Developing RESTful Web services with JAX-RS
Ad

Similar to Docker and Django Meet For A Tango - London Meetup (20)

PDF
Dockerize a Django app elegantly
PDF
PDXPortland - Dockerize Django
PDF
Running Django on Docker: a workflow and code
PPTX
Django via Docker
PDF
Future of Development and Deployment using Docker
PDF
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기
PPTX
Pycon Australia 2015: Docker + Python
PDF
Data Science Workflows using Docker Containers
PDF
Containerization is more than the new Virtualization: enabling separation of ...
PDF
dkr_django_slides
PDF
Keep it simple web development stack
KEY
Django deployment with PaaS
PDF
Deliver Python Apps with Docker
PDF
Docking postgres
PDF
Containerization Is More than the New Virtualization
PPTX
Develop with docker 2014 aug
PDF
Dockercon EU 2014
PPTX
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
PDF
Py conkr 20150829_docker-python
Dockerize a Django app elegantly
PDXPortland - Dockerize Django
Running Django on Docker: a workflow and code
Django via Docker
Future of Development and Deployment using Docker
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기
Pycon Australia 2015: Docker + Python
Data Science Workflows using Docker Containers
Containerization is more than the new Virtualization: enabling separation of ...
dkr_django_slides
Keep it simple web development stack
Django deployment with PaaS
Deliver Python Apps with Docker
Docking postgres
Containerization Is More than the New Virtualization
Develop with docker 2014 aug
Dockercon EU 2014
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
Py conkr 20150829_docker-python
Ad

Recently uploaded (20)

PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
PDF
Time Tracking Features That Teams and Organizations Actually Need
PPTX
Computer Software and OS of computer science of grade 11.pptx
DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PDF
MCP Security Tutorial - Beginner to Advanced
PPTX
Trending Python Topics for Data Visualization in 2025
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PDF
Digital Systems & Binary Numbers (comprehensive )
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Introduction to Windows Operating System
PPTX
Custom Software Development Services.pptx.pptx
PDF
STL Containers in C++ : Sequence Container : Vector
PDF
Cost to Outsource Software Development in 2025
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PPTX
chapter 5 systemdesign2008.pptx for cimputer science students
PPTX
Cybersecurity: Protecting the Digital World
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Oracle Fusion HCM Cloud Demo for Beginners
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Time Tracking Features That Teams and Organizations Actually Need
Computer Software and OS of computer science of grade 11.pptx
How to Use SharePoint as an ISO-Compliant Document Management System
MCP Security Tutorial - Beginner to Advanced
Trending Python Topics for Data Visualization in 2025
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
Digital Systems & Binary Numbers (comprehensive )
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Autodesk AutoCAD Crack Free Download 2025
Salesforce Agentforce AI Implementation.pdf
Introduction to Windows Operating System
Custom Software Development Services.pptx.pptx
STL Containers in C++ : Sequence Container : Vector
Cost to Outsource Software Development in 2025
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
chapter 5 systemdesign2008.pptx for cimputer science students
Cybersecurity: Protecting the Digital World

Docker and Django Meet For A Tango - London Meetup

  • 1. Copyright 2019 © systemati.co Docker and Django Meet For A Tango Hendrik Frentrup hendrik@systemati.co 15 July 2019 London, UK
  • 2. Copyright 2019 © systemati.co Ways to get in touch hendrik@systemati.co @HendrikFrentrup linkedin.com/in/frentrup/ github.com/hendrikfrentrup medium.com/@hendrik.frentrup
  • 3. Copyright 2019 © systemati.co Links •GitHub repo for the code •github.com/hendrikfrentrup/docker-django •Walkthrough: •medium.com/devopslinks/tech-edition-how-to-dockerize-a-django-web- app-elegantly-924c0b83575d •https://medium.com/@hendrik.frentrup/tech-edition-django-dockerization- with-bells-and-whistles-and-a-tad-bit-of-cleverness-2b5d1b57e289 •Further reading: •medium.com/panaseer-labs-engineering-data-science/how-devops- helped-us-solve-our-big-data-development-problem-263474dfeedb •Contact details: •Email: hendrik@systemati.co •Twitter: @hendrikfrentrup •LinkedIn: linkedin.com/in/frentrup/
  • 4. Copyright 2019 © systemati.co Code! • This will be a pretty detailed walk-through • There will be a lot of code in detail • Sometimes I’ll flick through things pretty quickly • I’ll make the slides available
  • 5. Copyright 2019 © systemati.co The Problem • Moving code from development environments to staging or production can break things • The state of environments drifts and is hard to manage • For lack of access, developers have no insight into the specifics of production environments
  • 6. Copyright 2019 © systemati.co Why? • Ease the pain of moving from Dev to Prod • Step towards being Cloud Native • Twelve Factor App (https://12factor.net/) • Infrastructure-as-Code • Productivity
  • 7. Copyright 2019 © systemati.co From here Application Database Local machine
  • 8. Copyright 2019 © systemati.co To here Docker web gunicorn server db postgres Local machine db-admin pgadmin server nginx nginx server python manage.py runserver *.conf + static/ pg-data/
  • 9. Copyright 2019 © systemati.co • Move a locally running app into a container • Setup database, admin and nginx services • Run migrations • Logging • Implement Infrastructure-as-code • Bring development and production environments close together • Increase productivity & working collaboratively Outline
  • 10. Copyright 2019 © systemati.co Simple app running locally python manage.py runserver db.sqlite3 Local machine
  • 11. Copyright 2019 © systemati.co 10 commands to set up > git init > git checkout -b develop > virtualenv env > source env/bin/activate > pip install Django>=2.1 > echo 'Django>=2.1' >> requirements.txt > django-admin startproject my-site > git add * && git commit -m "..." > python mysite/manage.py runserver
  • 12. Copyright 2019 © systemati.co App running in container Docker web python manage.py runserver db.sqlite3 Local machine
  • 13. Copyright 2019 © systemati.co App inside Docker > touch Dockerfile > docker build -t django-docker:0.0.1 . > docker run -p 8001:8001 docker-django:0.0.1 ______Dockerfile____________________________________________________________ FROM python:3.6.7-alpine ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code ADD ./ /code/ RUN pip install -r requirements.txt CMD ["python", "mysite/manage.py", "runserver", "0.0.0.0:8001"]
  • 14. Copyright 2019 © systemati.co Success looks like …
  • 15. Copyright 2019 © systemati.co Local storage Docker web python manage.py runserver db.sqlite3db.sqlite3 Local machine
  • 16. Copyright 2019 © systemati.co Moving to docker-compose > touch docker-compose.yml > docker-compose up ______docker-compose.yml__________________________________________________ version: "3" services: web: build: . command: python mysite/manage.py runserver 8001 ports: - “8001:8001” volumes: - ./mysite/:/code maps ports and container code/db to local filesystem
  • 17. Copyright 2019 © systemati.co Database service Docker web python manage.py runserver db postgres Local machine
  • 18. Copyright 2019 © systemati.co Adding a database service ______docker-compose.yml__________________________________________________ version: "3" services: web: build: . command: python mysite/manage.py runserver 8001 ports: - “8001:8001” volumes: - ./mysite/:/code db: image: postgres networks: - backend networks: backend: driver: bridge
  • 19. Copyright 2019 © systemati.co Handling env. variables ______settings.py____________________________________________________________ POSTGRES_PASSWORD = os.environ.get('POSTGRES_PASSWORD') DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'postgres', 'USER': 'postgres', 'PASSWORD': POSTGRES_PASSWORD, 'HOST': ‘db', 'PORT': '5432', }, ______.env__________________________________________________________________ POSTGRES_PASSWORD=secret POSTGRES_USER=postgres DJANGO_SECRET_KEY=secret > touch .env > echo 'psycopg2-binary' >> requirements.txt
  • 20. Copyright 2019 © systemati.co Credentials in envvars ______docker-compose.yml__________________________________________________ version: "3" services: web: [...] environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_USER: ${POSTGRES_USER} db: [...] environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_USER: ${POSTGRES_USER}
  • 21. Copyright 2019 © systemati.co Rebuilding the web image ______Dockerfile____________________________________________________________ FROM python:3.6.7-alpine ENV PYTHONUNBUFFERED 1 RUN apk update && apk add --virtual build-deps gcc python-dev musl-dev && apk add postgresql-dev RUN mkdir /code WORKDIR /code ADD ./ /code/ RUN pip install -r requirements.txt
  • 22. Copyright 2019 © systemati.co A bit of admin > docker-compose exec web python mysite/manage.py migrate > docker-compose exec web python mysite/manage.py createsuperuser Run that every time we tear down our containers? Note down the credentials we’ve used?
  • 23. Copyright 2019 © systemati.co Data migrations ______0001_initial.py___________________________________________________________ import os from django.db import migrations class Migration(migrations.Migration): dependencies = [] def generate_superuser(apps, schema_editor): from django.contrib.auth.models import User DJANGO_SU_NAME = os.environ.get('DJANGO_SU_NAME') DJANGO_SU_EMAIL = os.environ.get('DJANGO_SU_EMAIL') DJANGO_SU_PASSWORD = os.environ.get('DJANGO_SU_PASSWORD') superuser = User.objects.create_superuser( username=DJANGO_SU_NAME, email=DJANGO_SU_EMAIL, password=DJANGO_SU_PASSWORD) superuser.save() operations = [ migrations.RunPython(generate_superuser), ]
  • 24. Copyright 2019 © systemati.co More credentials ______docker-compose.yml__________________________________________________ version: "3" services: web: [...] environment: DJANGO_DB_NAME: ${DJANGO_DB_NAME} DJANGO_SU_NAME: ${DJANGO_SU_NAME} DJANGO_SU_EMAIL: ${DJANGO_SU_EMAIL} DJANGO_SU_PASSWORD: ${DJANGO_SU_PASSWORD} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_USER: ${POSTGRES_USER}
  • 25. Copyright 2019 © systemati.co web, db and admin services Docker web python manage.py runserver db postgres Local machine db-admin pgadmin server
  • 26. Copyright 2019 © systemati.co Adding a DB admin service ______docker-compose.yml__________________________________________________ [...] db-admin: image: dpage/pgadmin4 environment: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD} depends_on: - db ports: - "8080:80" networks: - backend [...]
  • 27. Copyright 2019 © systemati.co pgadmin in action
  • 28. Copyright 2019 © systemati.co Local app for debugging Docker web python manage.py runserver db postgres Local machine db-admin pgadmin server python manage.py runserver
  • 29. Copyright 2019 © systemati.co Run a local app alongside ______settings.py____________________________________________________________ from decouple import config SECRET_KEY = config(‘DJANGO_SECRET_KEY') DEBUG = config('DJANGO_DEBUG', default=False, cast=bool) WEB_HOST = config('DJANGO_WEB_HOST', default='localhost') DB_HOST = config('DJANGO_DB_HOST', default='localhost') DB_NAME = config(‘DJANGO_DB_NAME’) [...] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'postgres', 'USER': POSTGRES_USER, 'PASSWORD': POSTGRES_PASSWORD, 'HOST': DB_HOST, 'PORT': '5432', },
  • 30. Copyright 2019 © systemati.co Run a local app alongside ______docker-compose.yml_____________________________________ [...] environment: DJANGO_DEBUG: "True" DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY} DJANGO_DB_HOST: “db" [...]
  • 31. Copyright 2019 © systemati.co With nginx Docker web gunicorn server db postgres Local machine db-admin pgadmin server nginx nginx server python manage.py runserver
  • 32. Copyright 2019 © systemati.co Add nginx server ______default.conf_______________________________ server { listen 80; server_name localhost; location / { proxy_pass http://web:8001; } } ______settings.py________________________________ [...] ALLOWED_HOSTS = [WEB_HOST, ‘localhost'] [...] > echo “gunicorn” >> requirements.txt
  • 33. Copyright 2019 © systemati.co Add nginx server ______docker-compose.yml__________________________________________________ [...] web: command: gunicorn mysite.wsgi --bind 0.0.0.0:8001 [...] nginx: image: nginx:latest ports: - 8088:80 volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf networks: - backend depends_on: - web [...]
  • 34. Copyright 2019 © systemati.co Static files & persistent data Docker web gunicorn server db postgres Local machine db-admin pgadmin server nginx nginx server python manage.py runserver *.conf + static/ pg-data/
  • 35. Copyright 2019 © systemati.co Serving static assets ______settings.py_______________________________________ [...] STATIC_ROOT = os.path.join(BASE_DIR, 'static') > python mysite/manage.py collectstatic ______default.conf_____________________ server { [...] location /static { alias /code/static; } }
  • 36. Copyright 2019 © systemati.co Serving static assets ______docker-compose.yml__________________________________________________ [...] nginx: [...] volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./mysite/static:/code/static [...] db: volumes: - ./postgres-data:/var/lib/postgresql/data [...]
  • 37. Copyright 2019 © systemati.co Mapped ports Docker web 8001 db 5432 Local machine db-admin 8080 nginx 8088 8000
  • 38. Copyright 2019 © systemati.co Splitting YAML files ______docker-compose.override.yml_____________ [...] volumes: - ./mysite:/code environment: DJANGO_DEBUG: “True" [...] ______docker-compose.yml_______________ [...] web: build: . command: gunicorn mysite.wsgi --bind 0.0.0.0:8001 depends_on: - db networks: - backend [...]
  • 39. Copyright 2019 © systemati.co Logs
  • 40. Copyright 2019 © systemati.co Logging locally • To STDOUT!
  • 41. Copyright 2019 © systemati.co Logs in shared envs • Complex topic and no one size fits all • Log aggregator (SumoLogic, Splunk, ELK etc.) • A complete ELK stack in one container • Various logging driver options • Fluentd • Gelf Log aggregatorFluentd LogStash ElasticSearch Kibana
  • 42. Copyright 2019 © systemati.co Logging Local machine Staging environment Build server Log aggregator Production Code repo Local machine push trigger tail deploy stream deploy stream
  • 43. Copyright 2019 © systemati.co That’s all! Thanks