Необходимо:
- Установить все зависимости через пакетный менеджер
pip
. - Описать
Dockerfile
(описание синтаксиса) и собрать докер образ с помощью командыdocker build -t web_app -f dockerfiles/Dockerfile .
, где аргументы-t
- имя тега образа,-f
путь доDockerfile
. - Запустить контейнер на основе собранного на предыдущем шаге образа с помощью команды
docker run --rm -it -p 8000:8000 web_app
. В командеdocker run
(см. здесь) аргументы-p
означает открытие порта в контейнере и его соотвествие на хост машине,--rm
- удаление контейнера после завершения открытой сессии терминала контейнера,-it
- интерактивный режим запуска контейнера, то есть будут видны логи и запущенные процессы в контейнере, а альтертивой является запуск контейнера в виде демона через аргумент-d
. - Открываем браузер на хост машине и переходим на
localhost:8000
и видим запущенное приложение на Django!
До того, как запускать веб приложение необходимо подготовить контейнер с базой данных, к которой он будет коннектиться.
Контейнер базы данных
- В нашем примере мы не будем описывать свой
Dockerfile
для бд, а возьмем уже готовый образpostgres:12
с docker hub. Но до запуска необходимо подготовить .env файл, в котором будут установлены переменные окружения. В данном случае, для этого образа можно прописать следующие переменные:POSTGRES_DB
- название базы данныхPOSTGRES_USER
- имя пользователяPOSTGRES_PASSWORD
- пароль пользователя
- Запустить контейнер базы данных можно через команду
docker run --rm -it --name db --env-file .env -p 5432:5432 -v ${PWD}/pgdata:/var/lib/postgresql/data postgres:12
, где--name
- аргумент имени контейнера,--env-file
- путь до файла с переменными окружениями, а-v
-volume
- это монтирование папки с данными между хост машиной и контейнером
Контейнер веб приложения
- Для того чтобы приконнектиться к контейнеру с базой данных необходимо установить библиотеку
psycopg2
, а также изменить вsettings.py
переменнуюDATABASES
с переменными окружения из файла.env
(не забыть добавить--env-file
в командуdocker run
) - Значение переменной
HOST
можно установить по-разному в зависимости от способа линковки контейнеров:- Либо через аргумент
--link <container_name>
командыdocker run
. И тогда значениеHOST
будет равно значению<container_name>
. С помощью такого способа docker добавит в/etc/hosts
DNS запись, в которой будет указан IP контейнера. - Либо явно задать IP контейнера, можно зайти в контейнер бд через команду
docker exec -it <container_name> bash
и узнать его IP-адрес с помощьюcat /etc/hosts
- Либо через аргумент
- Запустить контейнер, например, через команду
docker run --rm -it -p 8000:8000 --link db --env-file .env web_app
Запуск веб приложения через python manage.py runserver
запускает один процесс и один поток обработки запросов. Такой способ подходит для локальной разработки, но не подходит для production
версии. Для неё необходимо воспользоваться специализированным веб-сервером, поддерживающим wsgi
протокол. Обычного это gunicorn
или uwsgi
. В данном примере воспользуемся gunicorn
.
Необходимо:
-
Установить пакет
gunicorn
и изменить команду запуска контейнера наgunicorn project.wsgi:application --bind 0.0.0.0:8000 --workers=4
, где аргументы--workers
- количество воркеров, то есть процессов, который будут обрабатывать запросы,--bind
- указывает серверный сокет для привязки воркеров с ним. -
Выдача статичных файлов (например, css, fonts, images). Чтобы отдавать статику в режиме запуска приложения через
gunicorn
можно воспользоваться прокси серверомnginx
(поднять для него отдельный контейнер), который будет сам отдавать статику, а для запросов не к статичным файлам будет перенаправлять запрос к Django приложению пример, nginx.conf. Более простой способ - это установить библиотекуWhiteNoise
. Она позволяет кэшировать и сжимать (вgzip
формат) содержимое файлов при выдачи ответа. Помимо установки необходимо добавить вsettings.py
middleware'whitenoise.middleware.WhiteNoiseMiddleware'
и установить переменнуюSTATIC_ROOT
чтобы указать путь до папки, куда будет генерироваться статичные файлы через командуpython manage.py collectstatic --noinput
(подробнее здесь). Поэтому необходимо расширить команду запуска веб контейнера.