Руководство по первоначальной настройке VDS/VPS сервера и деплою Django приложения в Docker контейнере на Ubuntu Server 20.04 / 22.04 LTS
Пройдя шаги описанные ниже вы получите контейнеризированное Django приложение подключённое к базе данных Postgresql, настроенный Nginx, работающий в качестве прокси сервера и обслуживающий статические файлы приложения, а также получим SSL сертификат для домена от Let's Encrypt и настроим его автоматическое обновление. Для успешного запуска тестового приложения понадобится доменное имя и оплаченный VDS/VPS сервер. Также необходимо в настройках DNS вашего домена создать А - запись указывающую на IP адрес вашего сервера, купленного заранее. Руководство актуально для облачных серверов провайдера Timeweb. В других случаях могут потребоваться дополнительные настройки и установка ПО. Например для нормальной работы этого руководства на VDS/VPS серверах провайдера Firstvds необходимо установить самостоятельно пакет snapd
и убедится, что базы данных создаются с кодировкой UTF-8
. По умолчанию будет установлена кодировка LATIN1
, что может вызывать сбои в работе приложения.
Данное руководство не является ультимативным гайдом по деплою Django приложений. Это всего лишь небольшая памятка для автора этих строк, которая может быть полезна ещё кому-то. Какие-то решения могут быть неэффективными, какие-то небезопасными. Но к концу этих строк мы получим настроенный VDS/VPS сервер с работающим сайтом, взрослой базой данных и SSL сертификатом. Критика и помощь в совершенствовании приветствуются.
- подключится по ssh:
ssh root@<server_ip>
<server_ip>
- это IP адресс VDS/VPS сервера, выдается провайдером. После ввода команды необходимо авторизироваться на сервере по паролю, полученным от провайдера после создания VDS/VPS сервера.
- создать нового пользователя:
adduser <username>
- добавить пользователя в группу sudo:
usermod -aG sudo <username>
- переключится на нового пользователя:
su <username>
- протестировать права нового пользователя:
sudo ls -a /root
Терминал должен отобразить папки и файла содержащиеся в /root.
sudo apt update
sudo apt upgrade
sudo apt install nginx
- Установка Postgresql для Ubuntu 20.04
sudo apt install postgresql-12
- Установка Postgresql для Ubuntu 22.04
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo apt install postgresql-12
Для установки Docker выполнить следующие команды:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
- проверить установку Docker:
docker --version
- За подробностями обращайтесь к официальной документации: Install Docker using the repository
Для установки Compose выполнить следующие команды:
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
- проверить установку Compose:
docker-compose --version
- За подробностями обращайтесь к официальной документации: Install Compose
- запустить консоль psql:
sudo -u postgres psql
- создать базу данных:
CREATE DATABASE <db_name>;
- создать пользователя:
CREATE USER <username> WITH PASSWORD '<password>';
- предоставить пользователю административный доступ к базе данных:
GRANT ALL PRIVILEGES ON DATABASE <db_name> TO <username>;
В контексте данного руководства замените
<db_name>
наtest_db
,<username>
наuser_postgres
,<password>
на0000
. В случае использования собственных значений не забудьте внести изменения в переменную DATABASES. Внимание! Не храните чувствительные данные в файлах приложения, используйте для этого переменные окружения. В данном руководстве пароли и имена пользователей хранятся в файлах приложения для просты восприятия.
Шаги под спойлером можно пропостуть, рекомендуется выполнить на боевой базе данных
Выполнить рекомендации по оптимизации Postgresql из официальной докуметации Django:
ALTER ROLE <username> SET client_encoding TO 'utf8';
ALTER ROLE <username> SET default_transaction_isolation TO 'read committed';
ALTER ROLE <username> SET timezone TO 'UTC';
- покинуть консоль psql:
ctr+Z
Файлы Dockerfile, docker-entrypoint.sh и docker-compose.yml уже созданы и лежат в репозитории, просто ознакомтесь как работают и зачем нужны.
Файл Dockerfile содержит инструкции по созданию Docker образа на основе которого будет создаваться и запускаться контейнер с Django приложением. Вот так выглядит наш:
FROM python:3.9.5-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
RUN ["chmod", "+x", "docker-entrypoint.sh"]
ENTRYPOINT [ "./docker-entrypoint.sh" ]
Образ будет создан на основе официального образа python:3.9.5-slim, туда будет скопирован файл requirements.txt, затем установятся все зависимости. Далее будут скопированны файлы нашего приложения и выполнены инструкции из файла docker-entrypoint.sh. Вот его содержимое:
#!/bin/bash
# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput
# Apply database migrations
echo "Apply database migrations"
python3 manage.py migrate
# Start server
echo "Starting server"
gunicorn app_to_dockerize.wsgi:application --bind 0.0.0.0:8000 --workers 3
Последняя строка запустит сервер приложений gunicorn для обслуживания нашего Django проекта. Упаравлять Docker будем с помощью docker-compose. Compose обычно используется для работы с многоконтейнерными проектами, но и в данном случае docker-compose немного облегчает работу, а при развитии проекта может оказаться необходимым. Например, Compose предоставляет очень удобный интерфейс для работы с именованными томами, а они однозначно понадобятся если приложение будет немного сложнее, чем пример из этого руководства. Инструкции для docker-compose описываются в файле docker-compose.yml. Вот содержимое нашего:
version: "3.9"
services:
web:
build: .
volumes:
- ./static:/app/static
network_mode: "host"
restart: unless-stopped
Compose смотрит в Dockerfile, строит на его основе образ, а также определяет папку на хосте, куда будут собраны статические файлы. network_mode: "host" говорит о том, что сеть Docker контейнера будет открыта локальному хосту, без этого Nginx не увидит сеть контейнера. restart: unless-stopped говорит о том, что при перезагрузке сервера Docker контейнер будет стартовать автоматически, пока не будет остановлен намеренно.
- перейти в домашнюю директорию:
cd ~
- скачать Django приложение на сервер:
git clone https://github.com/YuriyCherniy/how-to-dockerize-django-app.git
- перейти в папку содержащую docker-compose.yml файл:
cd how-to-dockerize-django-app/app_to_dockerize/
- запустить создание и запуск контейнера:
sudo docker-compose up -d
Ключь
-d
говорит о том, что контейнер будет запущен в detached mode. Это значит, что после создания образа и запуска контейнера, консоль будет освобождена. Если хотите видеть подробности работы приложения опустите ключ.
Для полноценной работы Django приложения необходимо создать супер пользователя. Для этого необходимо запустить следующую команду: sudo docker exec -it <container_name> bash
<container_name>
необходимо заменить на имя контейнера. Контейнер должен быть в запущенном состоянии. Имя контейнера можно узнать с помощью командыsudo docker ps
. Теперь можно выполнять стандартные административные команды Django находясь на одном уровне с файлом manage.py.
- создать супер пользователя:
./manage.py createsuperuser
- вернуться в консоль сервера:
exit
- открыть файл:
sudo nano /etc/nginx/nginx.conf
- удалить всё и поместить следующее содержимое:
user <username>;
events {}
http {
include conf.d/app_to_dockerize;
}
<username>
замените на имя пользователя операционной системы, без этой строки приложение работать будет, но в Ubuntu 22.04 Nginx не сможет обрабатывать статические файлы, необходимые для отображения административной панели Django.
- открыть файл:
sudo nano /etc/nginx/conf.d/app_to_dockerize
- поместить следующее содержимое:
include /etc/nginx/mime.types;
upstream web_app {
server localhost:8000;
}
server {
listen 80;
server_name <your_domain.ru>;
location / {
proxy_pass http://web_app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
location /static/ {
root /home/<username>/how-to-dockerize-django-app/app_to_dockerize/;
}
}
<your_domain.ru>
замените на ваше доменное имя.<username>
замените на имя пользователя операционной системы.
- проверить конфигурационные файлы Nginx на синтаксические ошибки:
sudo nginx -t
- перезагрузить конфигурационные файлы Nginx:
sudo nginx -s reload
Если всё было сделанно правильно сайт должен открываться на вашем домене по http соединению.
Получение и обновление сертификата будет происходить в автоматическом режиме с помощью ACME-клиента certbot, для этого выполните следующие команды:
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
- проверить возможность автоматического обнавления сертификата:
sudo certbot renew --dry-run
Больше подробностей, в официальной инструкции: certbot.eff.org
Если всё сделанно верно, сайт будет доступен по защищённому протоколу https: https://your_domain.ru