Необходимо:
- Установить все зависимости через пакетный менеджер
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/hostsDNS запись, в которой будет указан 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.pymiddleware'whitenoise.middleware.WhiteNoiseMiddleware'и установить переменнуюSTATIC_ROOTчтобы указать путь до папки, куда будет генерироваться статичные файлы через командуpython manage.py collectstatic --noinput(подробнее здесь). Поэтому необходимо расширить команду запуска веб контейнера.