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	
comments powered by Disqus