Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Django Development with Docker
Cuong Tran - Docker Hanoi
About me
Cuong Tran
Community: Docker Hanoi Organizer
Job: Developer at Higgs Valley
Email: tranhuucuong91@gmail.com
Github: https://github.com/tranhuucuong91
Blog: http://tranhuucuong91.github.io/
Domain: Machine Learning, DevOps, Cloud
2
Agenda
1. Introduction Django Stack
2. Run Django Stack
3. Common activity
4. Problems and solutions (P&S)
5. Snippets
6. Q&A
3
1. Introduction Django Stack
4
Nginx
Django
PostgresRedis
1. Introduction Django Stack: Project Structure
├── docker-compose.yml
├── docker-env
├── nginx
│ ├── Dockerfile
│ └── sites-enabled
│ └── django_project
├── production.yml
├── README.md
└── web
├── docker_django
│ ├── apps
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── Dockerfile
├── manage.py
├── requirements.txt
└── static
├── images
│ └── django-pony.png
└── main.css
5
1. Introduction Django Stack: docker-compose.yml
version: "2"
services:
nginx:
#restart: always
build: ./nginx/
ports:
- "80:80"
volumes:
- /www/static
volumes_from:
- web
depends_on:
- web
6
web:
#restart: always
build: ./web
expose:
- "8000"
depends_on:
- postgres
- redis
volumes:
- ./web:/usr/src/app
- ./web/static:/usr/src/app/static
env_file: docker-env
environment:
DEBUG: 'true'
command: /usr/local/bin/gunicorn
docker_django.wsgi:application -w 2 -b :8000
--access-logfile /var/log/gunicorn.log
1. Introduction Django Stack: docker-compose.yml
postgres:
#restart: always
image: postgres:9.5
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data/
7
redis:
#restart: always
image: redis:3.2
ports:
- "6379:6379"
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:
2. Run Django Stack
# build stack
docker-compose build
# up stack
docker-compose up -d
# migrate data
docker-compose run --rm web /usr/local/bin/python manage.py
migrate
8
3. Common Activity: Run container
● View web
● Run command in container
● Show logs
● Connect database to container
9
3. Common Activity: Update git
● Edit and git commit
● Git ignore files for dev, test, prod environments
● Update git
10
3. Common Activity: Build container
● Rebuild docker images
● Push to private registry
● Update docker images in production
11
4. P&S: Handle `docker stop`
● When call docker stop, docker will send SIGTERM to main process
inside the container. And after a grace period (default 10s), docker will
send SIGKILL.
12Image Source: http://www.slideshare.net/LeszekGodlewski/advanced-linux-game-programming
4. P&S: Handle `docker stop`
● The main process need to handle the signal and graceful stop.
import sys, signal, time
def handler(signum = None, frame = None):
print('Signal handler called with signal', signum)
time.sleep(1) #here check if process is done
print('Wait done')
sys.exit(0)
for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]:
signal.signal(sig, handler)
while True:
time.sleep(6)
13
4. P&S: Startup order
Issue: Docker Compose:
● Will not wait until a container is "ready".
● Only until it’s running.
Solution:
● Use a tool such as wait-for-it or dockerize.
● (Or) Write your own wrapper script to perform a more application-specific
health check.
14Reference: https://docs.docker.com/compose/startup-order/
4. P&S: Startup order
wait-for-postgres.sh
#!/usr/bin/env bash
set -e
host="$1"
shift
cmd="$@"
until psql -h "$host" -U "postgres" -c 'l'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
exec $cmd
15
wait-for-it.sh
#!/usr/bin/env bash
# Use this script to test if a given TCP
host/port are available
cmdname=$(basename $0)
echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@"
1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
$cmdname host:port [-s] [-t timeout] [--
command args]
-h HOST | --host=HOST Host or IP under
test
-p PORT | --port=PORT TCP port under
test
...
4. P&S: Speed up `docker build`
Use .dockerignore
● Because docker will put current directory in build context.
● To increase the build's performance, you can exclude files and directories
by adding a .dockerignore file.
● Syntax like .gitignore.
16
4. P&S: Speed up `docker build`
Build cache
● The orders of command -> image layers -> build speed & image size &
storage capacity
1. Install fixed things before. Ex: library, runtime
2. Install changed things after. Ex: code
17
4. P&S: Limit Resources
cpu_shares: 73
cpu_quota: 50000
cpuset: 0,1
mem_limit: 1000000000
memswap_limit: 2000000000
18
5. Snippets
#--- Docker stats ---
# stats all service in docker compose directory
docker stats `docker-compose ps | tail -n+3|awk '{print $1}'`
# stats all docker container are running
docker stats `docker ps | awk '{print $NF}' | tail -n+2`
#--- Docker remove ---
# remove all stopped containers
docker ps -a | awk '/Exit/ {print $1}' | xargs -r docker rm
# remove all untagged images
docker images | awk '/^<none>/ {print $3}' | xargs -r docker rmi
# remove old version images
docker images | grep ro.lan:5001/tranhuucuong91/nginx | tail -n +4 | awk '{print $3}' | xargs -r docker rmi
19
5. Snippets (cont.)
Save all the images on docker-compose.yml and deploy on machine not
connected to the internet
# Save Compressed Images
IMAGES=`grep '^s*image' docker-compose.yml | sed 's/image://' | sort | uniq`
docker save $IMAGES | gzip > images.tar.gz
# Load Compressed Images
gunzip -c images.tar.gz | docker load
20
[1] https://github.com/tranhuucuong91/docker-training
[2] https://realpython.com/blog/python/django-development-with-docker-co
mpose-and-machine/
[3] https://github.com/pydanny/cookiecutter-django
[4] https://docs.docker.com/engine/reference/builder/
[5] https://docs.docker.com/compose/compose-file
References
21
Q&A
22

More Related Content

ContainerDayVietnam2016: Django Development with Docker

  • 1. Django Development with Docker Cuong Tran - Docker Hanoi
  • 2. About me Cuong Tran Community: Docker Hanoi Organizer Job: Developer at Higgs Valley Email: tranhuucuong91@gmail.com Github: https://github.com/tranhuucuong91 Blog: http://tranhuucuong91.github.io/ Domain: Machine Learning, DevOps, Cloud 2
  • 3. Agenda 1. Introduction Django Stack 2. Run Django Stack 3. Common activity 4. Problems and solutions (P&S) 5. Snippets 6. Q&A 3
  • 4. 1. Introduction Django Stack 4 Nginx Django PostgresRedis
  • 5. 1. Introduction Django Stack: Project Structure ├── docker-compose.yml ├── docker-env ├── nginx │ ├── Dockerfile │ └── sites-enabled │ └── django_project ├── production.yml ├── README.md └── web ├── docker_django │ ├── apps │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── Dockerfile ├── manage.py ├── requirements.txt └── static ├── images │ └── django-pony.png └── main.css 5
  • 6. 1. Introduction Django Stack: docker-compose.yml version: "2" services: nginx: #restart: always build: ./nginx/ ports: - "80:80" volumes: - /www/static volumes_from: - web depends_on: - web 6 web: #restart: always build: ./web expose: - "8000" depends_on: - postgres - redis volumes: - ./web:/usr/src/app - ./web/static:/usr/src/app/static env_file: docker-env environment: DEBUG: 'true' command: /usr/local/bin/gunicorn docker_django.wsgi:application -w 2 -b :8000 --access-logfile /var/log/gunicorn.log
  • 7. 1. Introduction Django Stack: docker-compose.yml postgres: #restart: always image: postgres:9.5 ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data/ 7 redis: #restart: always image: redis:3.2 ports: - "6379:6379" volumes: - redisdata:/data volumes: pgdata: redisdata:
  • 8. 2. Run Django Stack # build stack docker-compose build # up stack docker-compose up -d # migrate data docker-compose run --rm web /usr/local/bin/python manage.py migrate 8
  • 9. 3. Common Activity: Run container ● View web ● Run command in container ● Show logs ● Connect database to container 9
  • 10. 3. Common Activity: Update git ● Edit and git commit ● Git ignore files for dev, test, prod environments ● Update git 10
  • 11. 3. Common Activity: Build container ● Rebuild docker images ● Push to private registry ● Update docker images in production 11
  • 12. 4. P&S: Handle `docker stop` ● When call docker stop, docker will send SIGTERM to main process inside the container. And after a grace period (default 10s), docker will send SIGKILL. 12Image Source: http://www.slideshare.net/LeszekGodlewski/advanced-linux-game-programming
  • 13. 4. P&S: Handle `docker stop` ● The main process need to handle the signal and graceful stop. import sys, signal, time def handler(signum = None, frame = None): print('Signal handler called with signal', signum) time.sleep(1) #here check if process is done print('Wait done') sys.exit(0) for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]: signal.signal(sig, handler) while True: time.sleep(6) 13
  • 14. 4. P&S: Startup order Issue: Docker Compose: ● Will not wait until a container is "ready". ● Only until it’s running. Solution: ● Use a tool such as wait-for-it or dockerize. ● (Or) Write your own wrapper script to perform a more application-specific health check. 14Reference: https://docs.docker.com/compose/startup-order/
  • 15. 4. P&S: Startup order wait-for-postgres.sh #!/usr/bin/env bash set -e host="$1" shift cmd="$@" until psql -h "$host" -U "postgres" -c 'l'; do >&2 echo "Postgres is unavailable - sleeping" sleep 1 done >&2 echo "Postgres is up - executing command" exec $cmd 15 wait-for-it.sh #!/usr/bin/env bash # Use this script to test if a given TCP host/port are available cmdname=$(basename $0) echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } usage() { cat << USAGE >&2 Usage: $cmdname host:port [-s] [-t timeout] [-- command args] -h HOST | --host=HOST Host or IP under test -p PORT | --port=PORT TCP port under test ...
  • 16. 4. P&S: Speed up `docker build` Use .dockerignore ● Because docker will put current directory in build context. ● To increase the build's performance, you can exclude files and directories by adding a .dockerignore file. ● Syntax like .gitignore. 16
  • 17. 4. P&S: Speed up `docker build` Build cache ● The orders of command -> image layers -> build speed & image size & storage capacity 1. Install fixed things before. Ex: library, runtime 2. Install changed things after. Ex: code 17
  • 18. 4. P&S: Limit Resources cpu_shares: 73 cpu_quota: 50000 cpuset: 0,1 mem_limit: 1000000000 memswap_limit: 2000000000 18
  • 19. 5. Snippets #--- Docker stats --- # stats all service in docker compose directory docker stats `docker-compose ps | tail -n+3|awk '{print $1}'` # stats all docker container are running docker stats `docker ps | awk '{print $NF}' | tail -n+2` #--- Docker remove --- # remove all stopped containers docker ps -a | awk '/Exit/ {print $1}' | xargs -r docker rm # remove all untagged images docker images | awk '/^<none>/ {print $3}' | xargs -r docker rmi # remove old version images docker images | grep ro.lan:5001/tranhuucuong91/nginx | tail -n +4 | awk '{print $3}' | xargs -r docker rmi 19
  • 20. 5. Snippets (cont.) Save all the images on docker-compose.yml and deploy on machine not connected to the internet # Save Compressed Images IMAGES=`grep '^s*image' docker-compose.yml | sed 's/image://' | sort | uniq` docker save $IMAGES | gzip > images.tar.gz # Load Compressed Images gunzip -c images.tar.gz | docker load 20
  • 21. [1] https://github.com/tranhuucuong91/docker-training [2] https://realpython.com/blog/python/django-development-with-docker-co mpose-and-machine/ [3] https://github.com/pydanny/cookiecutter-django [4] https://docs.docker.com/engine/reference/builder/ [5] https://docs.docker.com/compose/compose-file References 21