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

Создание приложения SaaS: за пределами основ (часть II)

К концу этого поста у вас будет развертываемое приложение, которое будет готово к эффективному обслуживанию реальных пользователей … Tagged с Python, JavaScript, Docker.

К концу этого поста у вас будет развертываемое приложение, которое будет готово обслуживать реальных пользователей эффективно и надежно!

Если вы не читали первый пост в серии, это пошаговое руководство по созданию приложения SaaS, которое выходит за рамки оснований, показывая, как делать все, от принятых платежей до управления пользователями. Примером проекта является трекер ранга Google, который мы создадим кусочком по частям, но вы можете применить эти уроки к любому приложению SaaS.

В последнем посте мы построили сценарий кукловода, который сделает фактическое соскабливание. В этом посте мы сосредоточимся на инфраструктуре, а именно на том, как настроить и развернуть приложение.

Для этого проекта я использую Nginx, Flask и Postgres на заднем плане. Мы будем использовать React для фронта. Docker и Docker Compose облегчат развертывание в любом месте.

Вы можете найти полный код на GitHub.

Оглавление

  • Часть I: Создание скребка поиска Google
    • Настройка кукловода на экземпляре AWS
    • Создание простого запроса поиска в Google
    • Использование прокси -сети для запросов скребков
    • Сбор результатов поиска
    • Обработка ошибок скрещин
  • Часть II: Производственное готовое развертывание с Nginx, Flask и Postgres
    • Настройка Docker и Docker Compose
    • Развертывание версии разработки
    • Понимание того, как nginx и колба работают вместе
    • Тестирование Nginx и Flask конфигурация
    • Конфигурация Postgres
    • Настройка SSL с помощью Let’s Encrypt
    • Развертывание производственной версии
  • Часть III: Колба, sqlalchemy и postgres
    • Настройка sqlalchemy и postgres
    • SQLalchemy Performance Performation
    • Настройка нашего первого обработчика маршрута API
  • Часть IV: аутентификация пользователя с помощью колбы и реагировать
    • Защита API REST Flask Rest с помощью JSON Web Tokens
    • Обработка регистрации пользователя в колбе
    • Проверка электронной почты и активация учетной записи
    • Создание пользователя и отправка электронной почты активации
    • Защита страниц в приложении React
    • Добавление Google oauth в качестве опции регистрации

Настройка Docker и Docker Compose

Настоящее приложение SaaS будет развернуто во многих средах: ноутбуки для разработчиков, промежуточная среда и производственный сервер, и это лишь некоторые из них. Docker делает это и более простым, так и более последовательным процессом.

Docker сочиняет организует несколько контейнеров, чтобы мы могли надежно управлять всем приложением. Эта оркестровка ограничена, однако, одним хостом. Многим приложениям никогда не нужно будет масштабироваться за пределами одного хоста, но такие варианты, как Kubernetes, существуют, если ваше приложение станет таким успешным!

Чтобы начать, нам нужно будет установить Docker и Docker на хосте.

curl -fsSL https://get.docker.com -o get-docker.sh # Download install script.
sudo chmod u+x ./get-docker.sh # Make script executable.
sudo ./get-docker.sh 
sudo usermod -aG docker $USER # Add current user to the docker group.
newgrp docker # Reload groups so that changes take effect.

Docker теперь должен быть установлен. Используйте Docker PS Чтобы убедиться, что Docker установлен правильно. Вы должны увидеть что -то подобное.

ubuntu@ip-172-31-38-160:~$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Установка 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

Развертывание версии разработки

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

Как только репозиторий клонирован, вы можете запустить приложение, просто запустив Docker -Compose -u -d и ожидание изображений скачать и построить. Docker вытащит изображения Nginx и Postgres, а также создаст изображение для контейнера приложения.

Вы можете запустить Docker PS После того, как построение изображения и загрузка завершены. Вывод должен быть аналогичен ниже.

CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                                       NAMES
0cc1d1798b49   nginx                 "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds    0.0.0.0:80->80/tcp, :::80->80/tcp           openranktracker_nginx_1
eb3679729398   open-rank-tracker     "python tasks.py wor…"   51 seconds ago   Up 49 seconds                                               openranktracker_app-background_1
ab811719630a   open-rank-tracker     "gunicorn --preload …"   51 seconds ago   Up 49 seconds                                               openranktracker_app_1
df8e554d7b12   postgres              "docker-entrypoint.s…"   52 seconds ago   Up 50 seconds   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   openranktracker_database_1
68abe4d03f62   redis:5.0.4-stretch   "docker-entrypoint.s…"   52 seconds ago   Up 50 seconds   6379/tcp                                    openranktracker_redis_1

Если вы никогда раньше не использовали Docker, то это может показаться магией, но Dockerfile а также Docker-compose.yml Файлы содержат все соответствующие детали. Первый содержит инструкции по созданию контейнера API Flask, а второе определяет все изображения, которые составляют приложение.

Вы можете заметить, что у нас есть Docker-compose.yml а также Docker-Compose.prod.yml . Вот как мы управляем различиями в развертывании между разработкой и производственными версиями. Обычно существует несколько важных различий между средами, например, как обрабатываются сертификаты SSL.

Понимание того, как nginx и колба работают вместе

Хотя Flask имеет свой собственный встроенный веб-сервер, мы будем использовать Nginx для обработки запросов от пользователя. Веб -сервер Flask предназначен только для целей разработки и обслуживает запросы с использованием одного потока, что делает его непригодным для нашего API, и особенно не подходит для обслуживания статических файлов.

Nginx выступает в качестве прокси, пересылав запросы API в Flask. Мы будем использовать стрелобище, чтобы преодолеть нашу проблему с одним натченой колбой. Обилинный зал управляет пулом процессов, каждый из которых работает в собственном экземпляре колбы и балансировки нагрузки между ними. Это может показаться сложным, но настройка управляется всего лишь несколько небольших файлов.

Давайте посмотрим, как nginx.conf Сначала настроен.

worker_processes 4;

events { worker_connections 1024; }

http {
    include /etc/nginx/mime.types;

    server {
        listen 80;
        listen [::]:80;

        location / {
            root /static;
            try_files $uri $uri/ /index.html;

            add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
        }

        location /api {
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_pass http://unix:/sock/app.sock:/api;
        }
    }
}

сервер Блок говорит Nginx прослушать на порту 80, в то время как Место Блоки определяют, что должно произойти, когда URL -адрес запроса соответствует определенному шаблону. Порядок блоков местоположения важен – первый блок может соответствовать любому запросу, но второй блок более конкретный и применим к запросам, начиная с /api как их путь.

Второй блок местоположения пересылает запрос на Flask, используя proxy_pass директива. http://unix:/sock/ означает, что сетевой трафик будет превышать Unix Domain Socket Анкет app.sock это файл, который обменивается между Nginx и Flask – как чтение, так и записи из этого доменного файла для общения. Наконец, :/api означает, что принимающая сторона, колба, должна получить запросы с префиксом /api Анкет

X-Forwarded-Proto Компонент станет важным позже, когда мы представим SSL в нашей производственной конфигурации. Эта директива приведет к тому, что NGINX прокси -запросы с тем же протоколом, поэтому, если запрос был сделан по HTTPS, то Flask получит тот же запрос на HTTPS. Это важно при реализации таких функций, как подпись с Google, потому что библиотеки OAuth требуют, чтобы каждый запрос был сделан по SSL.

Теперь давайте посмотрим на раздел Docker-compose.yml Файл, который определяет, как развернуты Nginx и Flask.

version: '3'

volumes:
    sock:

services:
    nginx:
        image: nginx
        restart: always
        volumes:
            - ./nginx.conf:/etc/nginx/nginx.conf
            - sock:/sock
        ports:
            - "80:80"

    app:
        command: gunicorn --preload --bind=unix:/sock/app.sock --workers=6 wsgi
        restart: always
        image: open-rank-tracker
        build: .
        volumes:
            - sock:/sock

Самая важная часть здесь – это носок Определение тома. Объявив носок В качестве громкости верхнего уровня мы можем поделиться им между Nginx и Flask, позволяя им использовать его в качестве розетки домена Unix.

Тестирование Nginx и Flask конфигурация

Нам не нужно ждать, пока мы не создадим пользовательский интерфейс, чтобы проверить, работает ли эта конфигурация или нет. Вы можете проверить это развертывание с помощью браузера или даже простой программы командной строки, такой как Curl.

Поскольку мы еще не затронули пользовательский интерфейс, нам нужно создать базовый index.html Файл, прежде чем мы действительно сможем провести какое -либо тестирование. Создать index.html Файл под статическим каталогом в корне проекта.

sudo touch static/index.html
sudo bash -c 'echo "Hi, world" > static/index.html'
curl http://localhost

Использование Curl или переход в http://localhost (или на IP вашего сервера, если развернут в другом месте) в вашем браузере должен показать Привет, мир в ответ. Это означает, что запрос совпадал с первым блоком местоположения в nginx.conf – на самом деле любая запроса, которую вы отправляете, не начинается с /api должен вернуться Привет, мир в этот момент.

Если вы попытаетесь перейти к http://localhost/api В вашем браузере вы вместо этого увидите страницу Flask 404. Мы еще не определили никаких маршрутов в колбе, поэтому ожидается 404, но мы знаем, что Nginx и Flask настроены должным образом на этом этапе.

Конфигурация Postgres

Настройка Postgres с Docker довольно проста. Я покажу вам Docker-compose.yml Конфигурация ниже и пройдите через несколько наиболее важных разделов.

database:
    image: postgres
    restart: always
    volumes:
       - /var/lib/postgres:/var/lib/postgres
    expose:
       - 5432
    env_file:
       - variables.env

Мы называем службу База данных , что важно, потому что это имя хоста, которые могут использовать другие контейнеры для подключения к Postgres. Директива по объему отображает каталог на хосте в соответствующий каталог в контейнере, так что, если контейнер остановлен или убит, мы не потеряли данные.

разоблачить Директива позволяет другим контейнерам доступ к порту 5432, но не допускает доступ вне сети Docker. Это важное различие для целей безопасности. Мы также могли бы использовать порты Директива, которая позволит получить доступ к 5432 из Интернета. Это может быть полезно, если вы хотите удаленно подключиться, но в этот момент ваш пароль Postgres – единственное, что мешает всем миру получить доступ.

Наконец, env_file сообщает сочинять, где искать переменные среды. Эти переменные затем передаются в контейнер. Изображение Postgres имеет только одну необходимую переменную среды – Postgres_password Это должно быть определено, но мы определим и несколько других.

POSTGRES_USER
POSTGRES_PASSWORD
POSTGRES_HOST
POSTGRES_DB

Потому что они перечислены без значений в переменные.env , каждая переменная берет свое значение из среды хоста. Вы также можете жесткие значения кода внутри файла конфигурации, но лучше не допустить их управления источником, особенно с такими значениями, как пароли или клавиши API.

Давайте проверим подключение к экземпляру Postgres, используя PSQL программа командной строки. Сначала найдите идентификатор контейнера Postgres, используя Docker PS , а затем мы подключаемся локально, используя Docker Exec Анкет

docker exec -it ba52 psql -U pguser -d openranktracker

Если все пойдет хорошо, вас встретят с помощью подсказки Postgres Interactive Shell.

Настройка SSL с помощью Let’s Encrypt

Нам нужно будет настроить SSL -сертификаты через Let’s Encrypt, прежде чем мы сможем развернуть производственную версию приложения. Это быстрый процесс, который включает в себя доказательство, чтобы зашифровать, что вы являетесь владельцем сервера, после чего они будут выпускать файлы сертификатов.

Перед получением сертификата вам понадобится доменное имя. Я использую домены Google, но любой регистратор домена должен работать.

Установка агента Certbot является первым шагом в процессе.

sudo apt-get install -y certbot

Теперь мы можем запросить сертификат, но сначала убедитесь, что порт 80 доступен – если приложение работает, обязательно остановите его сначала, чтобы Certbot мог использовать порт 80.

sudo certbot certonly --standalone --preferred-challenges http -d openranktracker.com

Конечно, вы должны заменить OpenRankTracker.com с вашим собственным доменным именем. Сертификаты действительны в течение 90 дней, после чего требуется простой процесс обновления. Мы проведем настройку автоматического процесса обновления чуть позже.

Развертывание производственной версии

То, что мы создали до сих пор, отлично подходит для местного развития на ноутбуке. Однако в реальном мире наше приложение должно быть, по крайней мере, включить SSL. К счастью, не сложно сделать этот дополнительный шаг для нашей производственной конфигурации.

Мы воспользуемся техникой композиции, известной как Упаковка Чтобы изменить конфигурацию максимально простой. Вместо необходимости переопределить все в отдельном Docker-compose.prod.yml Файл, нам нужно только указать, что отличается, и эти разделы будут иметь приоритет.

version: '3'

services:
    nginx:
        image: nginx
        restart: always
        volumes:
            - /etc/letsencrypt:/etc/letsencrypt
            - ./nginx.prod.conf:/etc/nginx/nginx.conf
            - ./static:/static
            - sock:/sock
        ports:
            - "443:443"
            - "80:80"

Этот файл содержит только службу Nginx, потому что конфигурация для приложения и базы данных остается прежней. Раздел объемов раскрывает сертификат Let’s Encrypt в контейнер Nginx и модифицированный nginx.prod.conf использует сертификат для обслуживания приложения по HTTPS.

Давайте посмотрим на nginx.prod.conf Файл, чтобы увидеть, как обрабатывается SSL.

worker_processes 4;

events { worker_connections 1024; }

http {
    include /etc/nginx/mime.types;

    server {
        listen 80;
        listen [::]:80;
        server_name _;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl default_server;

        ssl_certificate /etc/letsencrypt/live/openranktracker.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/openranktracker.com/privkey.pem;

        location / {
            root /static;
            try_files $uri $uri/ /index.html;

            add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
        }

        location /api {
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_pass http://unix:/sock/app.sock:/api;
        }
    }
}

Это должно выглядеть в основном знакомым, за исключением того, что теперь у нас есть два блока сервера: один слушает на порту 80 и перенаправляет трафик на порт 443, в то время как другой слушает 443 и обслуживает приложение, а также статические файлы. Если вы попытаетесь перейти в HTTP -версию, ваш браузер должен быть немедленно перенаправлен на версию HTTPS.

Мы используем уклаженную команду с Compose, чтобы поднять приложение с этой конфигурацией.

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

И Престо! Теперь вы должны иметь запросы на обслуживание Nginx с SSL включены.

Что дальше?

Надеюсь, вам понравилась вторая часть серии приложений SaaS! Далее мы начнем создавать модель данных для приложения и настроем первый обработчик маршрута, чтобы скребок, который мы построили в первой части, имели место для сообщений о его результатах.

Оригинал: “https://dev.to/zchtodd_79/building-a-saas-app-beyond-the-basics-part-ii-1h90”