Рубрики
Без рубрики

Путешествие через Django и Docker: практические принципы развертывания производства и идеи

Основная цель этого урока – дать вам представление о некоторых из вещей, которые задействованы толкают P … Теги с Docker, Django, Python, Nginx.

Основная цель этого урока – дать вам представление о том, что некоторые из вещей, которые включали в себя Python WebApp, используя Docker в производстве.

Окончательный код можно найти в этом репозитории в случае застряния. https://github.com/zom-pro/django-docker

Вступление

Чтобы следить за этим учебником/руководством, вам необходимо иметь базовые знания Django (понять, как создавать приложения, настройки и т. Д.), Docker и Linux. На самом деле это не шаг за шагом, а также руководство. Что-то связано с чашкой чая, а не при попытке сделать что-то работать на срок завтрашнего дня.

Это руководство охватывает различные мероприятия, связанные с контейнерным развертыванием веб-приложения Django для производства. Это не предназначено для того, чтобы быть готовым продуктом, скорее введение, чтобы положить вам в правильный путь. Это статья, которую я хотел бы найти и прочитать в тот день, когда я пытался присматривать головой вокруг «реальных» развертываний.

Большую часть времени Hello World Tutorials слишком ориентированы на разработку, и недостаточно упор на требования более изготовленной (реального слова?) Окружающей среды. Это, конечно, огромная тема, и я только царапающую поверхность. Кроме того, эти статьи в основном основаны на Localhost (на вашей собственной машине). Это состоит в том, чтобы уменьшить сложность и потребность в AWS, Heroku, ETC счетов. Однако, если вы не хотите использовать виртуальную машину и скорее использовать EC2 в AWS, он должен быть относительно просто, насколько у вас есть доступ SSH.

Все ссылки, ссылающиеся я, – это альтернатива конкретной информации, но это только результаты моего (предвзятости) поиска Google.

Вы всегда можете бросить мне комментарий, если что-то нужно больше деталей/разъяснений и т. Д. (или если вы найдете ошибку). Помните, что это просто альтернативная реализация, поэтому, если вы не согласны с чем-то, выложите мне сообщение. В мою карьере я многому научился от дружеских и продуктивных дискуссий.

Секции индекс

Скопируйте и найдите, чтобы перейти к правильному разделу

  • Установите Ubuntu Server и Nginx на виртуальной машине VirtualBox
  • Начальная разработка докеров и конфигурация
  • Толкать контейнер в репозиторий, чтобы он мог быть вытащен в производство
  • Некоторые конфигурация докера

Установите Ubuntu Server и Nginx на виртуальной машине VirtualBox

Загрузите сервер Ubuntu ( https://ubuntu.com/download/server ) и установите его на виртуальную машину VirtualBox с настройками по умолчанию. Если вы еще не сделали этого раньше, в наши дни в значительной степени сохраняют значения по умолчанию, поэтому не беспокойтесь об этом. Чтобы разрешить подключение между вашей машиной и VM, используйте адаптер моста в качестве сети.

Совет: Потому что у вас нет графической среды в сервере Ubuntu, я не мог получить функциональность копирования вставки для работы Поэтому я установил SSH-сервер, чтобы облегчить использование (разрешить копировать пасту, и т. Д.) https://linuxize.com/post/how-to-enable-ssh-on-ubuntu-18-04/ . Итак, я SSH от моего местного терминала, где у меня есть все, что мне нужно.

Чтобы добавить некоторую безопасность (то, что вам определенно нужно в производстве), мы заблокируем порты, которые мы не будем использовать. Быстрый и простой способ защитить вашу виртуальную машину – использовать несложный брандмауэр. https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewaltu-with-ufw-on-ubuntu-18-04 Отказ Конфигурация, которую я использовал для UFW, – это (позволяет HTTP, HTTPS и SSH). В более производственной среде вы получите выгоду от VPN и позволять SSH Crath VPN или конфигурацию на основе хоста бастиона. Оба темы вышли из объема этого урока. Чтобы настроить UFW, используйте эти команды.

 sudo ufw allow from 192.168.0.16 to any port 22
 sudo ufw allow from 192.168.0.16 to any port 443
 sudo ufw allow from 192.168.0.16 to any port 80

Кончик: DiumperoceCean имеет отличные уроки, и они хорошая альтернатива для VM на облаке (дешевле и проще, чем обычно AWS, он будет зависеть от того, на каком обслуживании вы используете)

Теперь мы установим Nginx в VM. Это прямая установка APT. https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04 Отказ

Там много тонкой настройки, который можно сделать в Nginx, но он не имеет возможности этого урока.

Совет: почему не работает Nginx в качестве контейнера? Вы можете! Но в этом случае я решил не потому, что я не чувствовал, что мои требования нуждаются в этом. Это тип вариантов, которые необходимо решить на основе ваших функциональных и нефункциональных требований. Например, не идеально оптимизированная контейнерная Nginx может иметь проблемы с производительностью. https://stackoverflow.com/questions/49023800/performance-issues-running-nginx-in-a-docker-container

Я допустил ошибку, чтобы поспешить контейнерировать все под солнцем, когда что-то было прекрасно бежать непосредственно на ОС, как WebSivers и базы данных. Каждый случай будет другим, и, насколько принято решение было принято на основе требований, доступных в этом пункте, правильно документированным и проанализированным (множество исследований для разных альтернатив!), Тогда это правильное решение (потому что у вас не было лучшего один). Если вы чувствуете, что вы не могли добраться до дна, просто просмотрите его позже.

Как только вы установили NGINX настроить самозаписанный сертификат https://www.humankode.com/ssl/create-a-selfsigned-certificate-for-nginx-in-5-minutes . Этот шаг позволит вам использовать HTTPS (порт 443) После шагов в мастере (предыдущая ссылка) мой сертификат выглядит так:

[req]
default_bits = 2048
default_keyfile = localhost.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ca
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = UK
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = London
localityName = Locality Name (eg, city)
localityName_default = Rochester
organizationName = Organization Name (eg, company)
organizationName_default = localhost
organizationalUnitName = organizationalunit
organizationalUnitName_default = Development
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
commonName_max = 64
[req_ext]
subjectAltName = @alt_names
[v3_ca]
subjectAltName = @alt_names
[alt_names]
DNS.1 = vmlocalhost

Как видите, я позвонил моему имени хоста (в VM) VMLocalhost, поэтому измените имя хоста к этому https://linuxize.com/post/how-to-change-hostname-on-ubuntu-18-04/ Кроме того, вы хотите изменить свой хост-машина, чтобы он связал имя хоста VMLocalhost для его локального IP. (192.168.0.x), который был назначен вашим VM. Это то, что вам не придется делать, если бы вы использовали реальный сертификат, конечно.

Как только вы установили сертификат, настройте Nginx для перенаправления до 443 https://serverfault.com/questions/67316/in-nginx-how-can-i-rewrite-all-http-wrequests-to-https- Вступают– Моя конфигурация выглядит так (на данный момент! Окончательная версия можно найти в репозитории)

server {
  listen 80;
  server_name vmlocalhost;
  return 301 https://$server_name$request_uri;
}
server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;
  ssl_certificate /etc/ssl/certs/localhost.crt;
  ssl_certificate_key /etc/ssl/private/localhost.key;

  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;
  server_name vmlocalhost;
  location / {
    try_files $uri $uri/ =404;
  }
}

Начальная разработка докеров и конфигурация

Вернитесь к своему хозяину, чтобы начать с вашего жизненного цикла вашего развития. Идея состоит в том, что вы записываете свой код локально и когда вы довольны кодом, вы создаете контейнер локально. Как только вы довольны контейнером, вы толкаете его в репозиторий и потяните его на другую сторону (в этом случае VM). Обычно вы будете справиться с этим с каким-то видом Ci/Cd, как Circle CI (еще одна очень важная вещь, которую нужно сделать в производстве, но из объема этого учебника).

Создайте приложение Django в Localhost (нашей среде Dev) и проверьте его. Также вы можете добавить очень простое приложение, как тот, который у меня есть в моем репозитории GitHub, чтобы облегчить отладку и т. Д. После того, как вы можете увидеть ракета Django или вашу приложение, давайте получим бегущий контейнер. Вам нужно ознакомиться с DockerFile, но они довольно интуитивны. Мой выглядит так:

FROM python:3.8.2-slim-buster
RUN apt update & apt -y upgrade
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY . /code
RUN pip install -r requirements.txt
RUN chmod +x /code/docker-entrypoint.sh
ENTRYPOINT [ "/code/docker-entrypoint.sh" ]

Храните его в файле под названием DockerFile в корне проекта (если под сомнением посмотрите на репозиторий) и используйте его бегом:

sudo docker build -t djangodocker .
sudo docker run --rm -it -p 8000:8000 djangodocker

Все, что вам нужно в файле требований. Atxt прямо сейчас django. Ваш Docker-entrypoint.sh будет иметь инструкцию для запуска Django (а затем Gunicorn) так:

python manage.py runserver 0.0.0.0

Совет: Я вернулся к этому дню после и начал проблемы с контейнером, не желающим бегать. Чтобы отладить его, я следовал по этой инструкции: https://serverfault.com/questions/596994/how-can-i-debug-a-docker-container-initialization События и командование сказали мне, что не было ничего плохого, и я был глупым, моя выпускная точка остановила контейнер только заканчивая. Я просто удалил точку входа, чтобы контейнер не имел ничего общего, и он был правильно прекращается …

На данный момент изображение 232 МБ, я доволен этим. Alpine – отличная альтернатива Ubuntu/Debian, если вы хотите что-то меньшее, но убедитесь, что все ваши зависимости могут быть установлены в Alpine, прежде чем совершать его. Размер изображения может быть определенным фактором в некоторых средах, но опять же, что должно быть решено на основе требований проекта.

Теперь, чтобы показать вам мероприятие, связанную с контейнером. Хороший момент, чтобы узнать об этом и серверам приложений). Поэтому представьте, что ваши требования еще не включали Gunicorn (они делают в версии репозитории), и вы хотите запустить его, прежде чем создавать конечную точку для подключения к нему.

Перейдите в контейнер Dockerfile, удалите свою точку входа, постройте его снова и запустите ее, но на этот раз в интерактивном режиме (он приведет вас к экземпляру Bash внутри контейнера)

docker run -it --rm -p 8000:8000 djangodocker bash

Затем запустить гурунгу, установите его и запустите его

pip install gunicorn
gunicorn -b 0.0.0.0:8000 django_docker.wsgi

КОНЧИК: Чтобы избежать ожидания Gunicorn при запуске https://pythonspeed.com/articles/gunicorn-in-docker/

Теперь для нашей въездной точки мы заменим Runserver Django (лучше всего заменить то, что было там раньше). Здесь django_docker – ваше приложение (в каком папке вы должны найти файл wsgi.py, если вы находитесь в корне вашего проекта). С этой командой мы говорим Gunicorn привязать к порту, которую мы хотим. Если вам нужно что-то более сложное, чем это, вы можете создать файл конфигурации. https://docs.gunicorn.org/en/stable/configure.html Окончательная выходная точка выглядит так:

#!/bin/bash

# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput

# Apply database migrations
echo "Apply database migrations"
python manage.py migrate

# Start server
echo "Starting server"
gunicorn -b 0.0.0.0:8000 --workers=2 --threads=4 --worker-class=gthread django_docker.wsgi

Я собираю статическую и мигрирующую, что не является чем-то рекомендуемым для производства (см. Подробнее в конце статьи об этом), но это работает для нас только сейчас, потому что мы уничтожим дБ каждый раз, и мы только развертываем одну из этих контейнеров в время.

Теперь у нас должен быть рабочий контейнер докеров в вашей местной среде (DEV).

Толкать контейнер в репозиторий, чтобы он мог быть вытащен в производство

Это наш последний шаг. Вы можете использовать Docker Hub, чтобы нажать на ваше изображение https://ropenscilabs.github.io/r-docker-tutorial/04-Dockerhub.html

Вам нужно создать хранилище в Docker Hub. Это бесплатно для одного частного хранилища.

В вашем локальном хосте беги:

docker login --username=zompro(your username) --email=your@email.com
sudo docker tag djangodocker:latest zompro/djangodocker-repo:latest
sudo docker push zompro/djangodocker-repo:latest

Это будет войти в концентратор с вашими учетными данными (он попросит ваш пароль), тег (имя) ваше локальное изображение (вы будете использовать это, чтобы управлять версиями обычно) и подтолкнуть его к репозитору.

Если вы еще не сделали его, установите демон Docker на виртуальной машине https://docs.docker.com/install/linux/docker-ce/ubuntu/ Как только у вас есть демон Docker, запустите в своей виртуальной машине

docker login --username=zompro --email=your@email.com
sudo docker pull zompro/djangodocker-repo
sudo docker run --rm -it -p 8000:8000 zompro/djangodocker-repo

Убедитесь, что IP-адрес VM (или в моем случае мое имя хоста имени VMLocalhost, как мы настроили ранее), находится в разрешенных настройках (настройки Django).

Если вы еще этого не сделали, мы настроим NGINX, чтобы вы действовать как прокси-прокси для Gunicorn и служить нашим статическим файлам.

Добавить в конфигурацию Nginx

 location /static {
   alias /var/www/static/;
 }

И при запуске контейнера используйте (убедитесь, что статический каталог существует) ссылка на громкость, поэтому при сборке в вашем контейнере они доступны в этом каталоге для обслуживания Nginx.

docker run --rm -d -p 8000:8000 -v /var/www/static:/code/static zompro/djangodocker-repo

Перезагрузите страницу и следите за журналом Access Nignx, вы должны увидеть NGINX, обслуживающие ваши статические файлы.

tail -f /var/log/nginx/access.log

Например, в моем случае (первый IP находится с моей локальной машины, тот, который запрашивал страницу), и вы можете увидеть статический файл, обслуживаемый из нашего VMLocalhost

192.168.0.16 — — [29/Apr/2020:07:40:04 +0000] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 304 0 "https://vmlocalhost/static/admin/css/fonts.css" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36"

Некоторые конфигурация докера

Это большая тема, поэтому я просто хочу упомянуть пару вещей.

Все идет нормально Но мы все еще работаем в режиме отладки, и мы хотим контролировать какую среду (PROD, DEV) мы настраиваем наше приложение для. Мы хотим, чтобы вся конфигурация для докера поступила от внешних переменных (вместо того, чтобы иметь один контейнер для PROD и другой для DEV, который будет нулевым одним из самых больших преимуществ использования Docker).

Совет: Это может быть хорошим моментом для отделения до 12-факторных приложений (согласна ли вы или нет с ними, вы должны их понимать и не соглашаться, если вы сделаете, из информированной позиции).

Давайте изменим наши настройки Django немного, чтобы отразить использование переменных среды. Добавить сверху (всегда помните, что вы можете проверить файл в моем репозитории GitHUB для конечной части)

Environment.getenv («Окружающая среда»)

И тогда вы можете сделать что-то вроде этого (это простая версия, это может быть намного более элегантной)

DEBUG = False
if ENVIRONMENT == "development":
  DEBUG = True
ALLOWED_HOSTS = ["vmlocalhost"]
if ENVIRONMENT == "development":
   ALLOWED_HOSTS.append("127.0.0.1")

Кончик: Одна вещь, которую я люблю делать, всегда по умолчанию до менее опасного случая. Так что здесь, например, вы должны заставить систему быть в разработке «режим», чтобы обеспечить отладку. Так что, если вы забудете добавить (или плохую документацию, означает, что вы не знаете, что вы должны) Это не откроет возможную проблему безопасности по умолчанию. Многие системы поставляются с очень слабой конфигурацией по умолчанию (Admin для входа в систему и пароль – это классический) Так что следите за.

После внесения этого изменения в файле settings.py, если мы снова запустим наш контейнер после восстановления его в нашем localhost (sudo docker run –rm -it -p 8000: 8000 djangodocker), мы должны получить ошибку 400, потому что наша ошибка Dev не в разрешенных хостах (это моделирует вашу среду разработки). Чтобы избежать этой ошибки, передайте переменную среды как часть команды. Мы делаем что-то подобное с секретным ключом (которое никогда не следует хранить в вашем репозитории).

docker run --env ENVIRONMENT=development --env SECRET_KEY=super_secret_random_key --rm -it -p 8000:8000 djangodocker

Совет: Обычно вы обратитесь к этому как часть вашего файла .env, используя docker-compose. Я намеренно оставил Docker-Compose из этого учебника, потому что я думаю, что важно получить хорошее понимание команды Docker, прежде чем двигаться дальше Но это, вероятно, следующее место, где вы хотите пойти.

Некоторые последние советы

Одно следует учитывать для производственной среды, это то, что, вероятно, (зависит от вашего случая использования всегда), которые вы хотите запускать миграции «вручную». Это означает запустить команду docker exec для запуска миграции. Причина этого представить, что сценарий выпускали внешнюю БД (не SQLite внутри контейнера), который очень вероятно, будет вашим корпусом, и у вас появляется более одного избыточного контейнера, запускается, опять возможный сценарий. Если оба контейнера пытаются запускать миграции, когда они запускают одновременно, у вас будет беспорядок в руках. Но тогда они другие много вещей на стороне Джанго, такие как обработка секретного ключа Но мне пришлось где-то ограничить объем.

Многие (я имею в виду много) вещи были оставлены из этого руководства. Между ними: docker-compose (как упомянуто ранее), перезапустите политики (если вы должны использовать только Docker, чтобы контролировать свои услуги или что-то еще, как Systemd), Docker Networks (как есть тома, контейнеры, вы создаете сети между ними), и т.п. Как только вы поднялись на эти горы, вы поймете (или я по крайней мере, я сделал), что они были холмом, и вы сейчас смотрите на Анды. Между некоторыми из самых высоких выборов вы найдете микросервисные архитектуры и их сложность, Куберовские и многие другие супер прохладные технологии. Мой совет, не начинайте подниматься на любой из них, если не нужно ясно и перед вами. Если вы бросаетесь, чтобы реализовать их, вы погрузите дыру технической задолженности от того, где вы можете не выйти.

Надеюсь, тебе понравилось. Я, конечно, сделал это. Помните, если он чувствует себя слишком сложным прямо сейчас, вы будете смеяться над тем, как просто и глупо, это 6 месяцев, если вы настойчивы. В какой-то момент мы все почесываем на наши головы, не понимая, что происходит.

Оригинал: “https://dev.to/zompro/a-journey-through-django-and-docker-hands-on-production-deployment-principles-and-ideas-17a3”