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

hendrik@systemati.co

31 January 2019

Auckland, NZ
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
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
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
• Infrastructure-as-code

• Bring development and production
environments close together

• Increased productivity
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
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
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 aggregator
Fluentd
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

Similar to Dockerize a Django app elegantly

Release webinar architecture
Release webinar   architectureRelease webinar   architecture
Release webinar architecture
BigData_Europe
 
Securing Containers - Sathyajit Bhat - Adobe
Securing Containers - Sathyajit Bhat - AdobeSecuring Containers - Sathyajit Bhat - Adobe
Securing Containers - Sathyajit Bhat - Adobe
CodeOps Technologies LLP
 
Set up a Development Environment in 5 Minutes
Set up a Development Environment in 5 MinutesSet up a Development Environment in 5 Minutes
Set up a Development Environment in 5 Minutes
Akamai Developers & Admins
 
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
InfluxData
 
Multi Stage Docker Build
Multi Stage Docker Build Multi Stage Docker Build
Multi Stage Docker Build
Prasenjit Sarkar
 
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
Cisco DevNet
 
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando HonigOSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
NETWAYS
 
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
Amazon Web Services Korea
 
Cloud computing & its Basic
Cloud computing & its BasicCloud computing & its Basic
Cloud computing & its Basic
Patrik Soleman
 
Declarative Import with Magento 2 Import Framework (M2IF)
Declarative Import with Magento 2 Import Framework (M2IF)Declarative Import with Magento 2 Import Framework (M2IF)
Declarative Import with Magento 2 Import Framework (M2IF)
Tim Wagner
 
DCEU 18: Developing with Docker Containers
DCEU 18: Developing with Docker ContainersDCEU 18: Developing with Docker Containers
DCEU 18: Developing with Docker Containers
Docker, Inc.
 
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
Amazon Web Services
 
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
AWS Summits
 
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
Amazon Web Services
 
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
Amazon Web Services Korea
 
Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
 Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트) Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
Amazon Web Services Korea
 
Http Services in Rust on Containers
Http Services in Rust on ContainersHttp Services in Rust on Containers
Http Services in Rust on Containers
Anton Whalley
 
Introduction To Containers - Builders Day Israel
Introduction To Containers - Builders Day IsraelIntroduction To Containers - Builders Day Israel
Introduction To Containers - Builders Day Israel
Amazon Web Services
 
Kubernetes Security Best Practices for DevOps
Kubernetes Security Best Practices for DevOpsKubernetes Security Best Practices for DevOps
Kubernetes Security Best Practices for DevOps
DevOps.com
 
Breaking the Monolith Using AWS Container Services
Breaking the Monolith Using AWS Container ServicesBreaking the Monolith Using AWS Container Services
Breaking the Monolith Using AWS Container Services
Amazon Web Services
 

Similar to Dockerize a Django app elegantly (20)

Release webinar architecture
Release webinar   architectureRelease webinar   architecture
Release webinar architecture
 
Securing Containers - Sathyajit Bhat - Adobe
Securing Containers - Sathyajit Bhat - AdobeSecuring Containers - Sathyajit Bhat - Adobe
Securing Containers - Sathyajit Bhat - Adobe
 
Set up a Development Environment in 5 Minutes
Set up a Development Environment in 5 MinutesSet up a Development Environment in 5 Minutes
Set up a Development Environment in 5 Minutes
 
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
Scaling Prometheus Metrics in Kubernetes with Telegraf | Chris Goller | Influ...
 
Multi Stage Docker Build
Multi Stage Docker Build Multi Stage Docker Build
Multi Stage Docker Build
 
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
Integrated, Automated Video Room Systems - Webex Devices - Cisco Live Orlando...
 
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando HonigOSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
OSDC 2019 | RTO & RPO – Best Practices in Hybrid Architectures by Fernando Honig
 
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
K8s, Amazon EKS - 유재석, AWS 솔루션즈 아키텍트
 
Cloud computing & its Basic
Cloud computing & its BasicCloud computing & its Basic
Cloud computing & its Basic
 
Declarative Import with Magento 2 Import Framework (M2IF)
Declarative Import with Magento 2 Import Framework (M2IF)Declarative Import with Magento 2 Import Framework (M2IF)
Declarative Import with Magento 2 Import Framework (M2IF)
 
DCEU 18: Developing with Docker Containers
DCEU 18: Developing with Docker ContainersDCEU 18: Developing with Docker Containers
DCEU 18: Developing with Docker Containers
 
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
Container Power Hour with Jess, Clare, and Abby (CON362) - AWS re:Invent 2018
 
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
 
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019Orchestrating containers on AWS  | AWS Summit Tel Aviv 2019
Orchestrating containers on AWS | AWS Summit Tel Aviv 2019
 
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
AWS Container Services – 유재석 (AWS 솔루션즈 아키텍트)
 
Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
 Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트) Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
Amazon Container Services – 유재석 (AWS 솔루션즈 아키텍트)
 
Http Services in Rust on Containers
Http Services in Rust on ContainersHttp Services in Rust on Containers
Http Services in Rust on Containers
 
Introduction To Containers - Builders Day Israel
Introduction To Containers - Builders Day IsraelIntroduction To Containers - Builders Day Israel
Introduction To Containers - Builders Day Israel
 
Kubernetes Security Best Practices for DevOps
Kubernetes Security Best Practices for DevOpsKubernetes Security Best Practices for DevOps
Kubernetes Security Best Practices for DevOps
 
Breaking the Monolith Using AWS Container Services
Breaking the Monolith Using AWS Container ServicesBreaking the Monolith Using AWS Container Services
Breaking the Monolith Using AWS Container Services
 

Recently uploaded

Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
SitimaJohn
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
Brandon Minnick, MBA
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 
Recommendation System using RAG Architecture
Recommendation System using RAG ArchitectureRecommendation System using RAG Architecture
Recommendation System using RAG Architecture
fredae14
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
ssuserfac0301
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
Federico Razzoli
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
Postman
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 
OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
David Brossard
 

Recently uploaded (20)

Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 
Recommendation System using RAG Architecture
Recommendation System using RAG ArchitectureRecommendation System using RAG Architecture
Recommendation System using RAG Architecture
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
 
Webinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data WarehouseWebinar: Designing a schema for a Data Warehouse
Webinar: Designing a schema for a Data Warehouse
 
WeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation TechniquesWeTestAthens: Postman's AI & Automation Techniques
WeTestAthens: Postman's AI & Automation Techniques
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 
OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
 

Dockerize a Django app elegantly

  • 1. Copyright 2019 © systemati.co Docker and Django Hendrik Frentrup hendrik@systemati.co 31 January 2019 Auckland, NZ
  • 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 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
  • 5. Copyright 2019 © systemati.co From here Application Database Local machine
  • 6. 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/
  • 7. Copyright 2019 © systemati.co • Move a locally running app into a container • Setup database, admin and nginx services • Run migrations • Logging • Infrastructure-as-code • Bring development and production environments close together • Increased productivity Outline
  • 8. Copyright 2019 © systemati.co Simple app running locally python manage.py runserver db.sqlite3 Local machine
  • 9. 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
  • 10. Copyright 2019 © systemati.co App running in container Docker web python manage.py runserver db.sqlite3 Local machine
  • 11. 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"]
  • 12. Copyright 2019 © systemati.co Success looks like …
  • 13. Copyright 2019 © systemati.co Local storage Docker web python manage.py runserver db.sqlite3db.sqlite3 Local machine
  • 14. 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
  • 15. Copyright 2019 © systemati.co Database service Docker web python manage.py runserver db postgres Local machine
  • 16. 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
  • 17. 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
  • 18. 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}
  • 19. 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
  • 20. 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?
  • 21. 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), ]
  • 22. 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}
  • 23. Copyright 2019 © systemati.co web, db and admin services Docker web python manage.py runserver db postgres Local machine db-admin pgadmin server
  • 24. 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 [...]
  • 25. 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
  • 26. 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', },
  • 27. 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" [...]
  • 28. 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
  • 29. 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
  • 30. 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 [...]
  • 31. 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/
  • 32. 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; } }
  • 33. 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 [...]
  • 34. Copyright 2019 © systemati.co Mapped ports Docker web 8001 db 5432 Local machine db-admin 8080 nginx 8088 8000
  • 35. Copyright 2019 © systemati.co Logs
  • 36. Copyright 2019 © systemati.co Logging locally • To STDOUT!
  • 37. 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 aggregator Fluentd LogStash ElasticSearch Kibana
  • 38. 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
  • 39. Copyright 2019 © systemati.co That’s all! Thanks