Django in Docker
There are many instructions how to run Django in Docker. The base configuration of docker-compose usualy has the next services: nginx, web (django), db (mysql, postgresql), cache (memcached, redis). I’ll just add some notes.
Environment variables
I keep the configuration variables in .env
file. For example:
MAILGUN_ACCESS_KEY=...
MYSQL_DATABASE=...
MYSQL_ROOT_PASSWORD=...
MYSQL_PATH=...
MEDIA_PATH=...
WEB_CONCURRENCY=...
In docker-compose
:
db:
...
environment:
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE
volumes:
- ${MYSQL_PATH}:/var/lib/mysql
web:
...
volumes:
...
- ${MEDIA_PATH}:/media
environment:
- WEB_CONCURRENCY
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE
- MAILGUN_ACCESS_KEY
Static and media volumes
About static
files I don’t care, they can be regenerated at any time, so I use a simple named volume. For media
I provide a full path, so they can be easily backed up.
web:
...
volumes:
- static:/static
- ${MEDIA_PATH}:/media
nginx:
...
volumes:
- static:/static
- ${MEDIA_PATH}:/media
volumes:
static:
For Nginx the directories in media
should have the x
permission.
Management commands
The management commands can be run from the web
container.
docker-compose -f docker-compose.yml run --rm web python manage.py collectstatic --noinput
docker-compose -f docker-compose.yml run --rm web python manage.py migrate
I have them in Makefile
as targets.
Management commands in cron
To run command in cron in the container based on Alpine.
Add dcron
into Dockerfile
and change entrypoint
RUN apk add --no-cache dcron
RUN touch /var/log/cron.log
...
ENTRYPOINT ["/app/start.sh"]
Add to the project start.sh
script
#!/bin/sh
chmod 0644 /etc/crontabs/root
/usr/sbin/crond -l 8
exec "$@"
Add crontab
file with empty line at the end
0 5 * * * /app/manage.py some_command >> /var/log/cron.log 2>&1
Link crontab
to container in volumes section:
web:
volumes:
...
- ./crontab:/etc/crontabs/root
MySQL dump
To dump db I have a target in the Makefile
.
DATE = $(shell date +%Y-%m-%d)
path ?= .
help: ## show this help
@echo 'usage: make [target] ...'
@echo ''
@echo 'targets:'
@egrep '^(.+)\:\ .*##\ (.+)' ${MAKEFILE_LIST} | sed 's/:.*##/#/' | column -t -c 2 -s '#'
dump: ## dump db, usage 'make dump path=/path/to/dumps'
docker-compose exec db sh -c 'mysqldump -u root -p"$$MYSQL_ROOT_PASSWORD" --add-drop-table --add-drop-database $$MYSQL_DATABASE' | gzip > $(path)/db-$(DATE).sql.gz
restore: ## restore db from dump file, usage 'make restore dump=dump.sql.gz'
docker-compose stop web
gunzip -c $(dump) | docker exec -i `docker-compose ps -q db` sh -c 'mysql -u root -p"$$MYSQL_ROOT_PASSWORD" $$MYSQL_DATABASE'
docker-compose start web