CI/CD v Github Actions pro projekt na Flasku a Angularu.

CI/CD v Github Actions pro projekt na Flasku a Angularu.
V tomto článku se podělím o své zkušenosti s nastavením CI/CD pomocí ovládacího panelu Plesk a Github Actions. Dnes se naučíme nasadit jednoduchý projekt s názvem „Helloworld“. Je napsán na Python frameworku Flask, s workery na Celery a frontendem na Angular 8.

Odkazy na repozitáře: backend, frontend.

V první části článku se podíváme na náš projekt a jeho části. Ve druhé části si ukážeme, jak nastavit Plesk a nainstalovat potřebná rozšíření a komponenty (DB, RabbitMQ, Redis, Docker atd.).

Ve třetí části konečně zjistíme, jak nastavit pipeline pro nasazení našeho projektu na server do dev- a prod- prostředí. A poté spustíme web na serveru.

A ano, zapomněl jsem se představit. Jmenuji se Oleg Borzov, jsem fullstack vývojář v týmu CRM pro manažery hypotečního úvěrování v Domklik.

Přehled projektu

Nejprve se podíváme na dvě repozitáře projektu — backend a frontend — a projdeme si kód.

Backend část: Flask+Celery

Pro backend jsem vzal dost populární kombinaci mezi Python vývojáři: framework Flask (pro API) a Celery (pro frontu úloh). Jako ORM je používáno SQLAlchemy. Pro migraci se používá Alembic. Pro validaci JSON v routech — Marshmallow.

V repozitáře existuje soubor Readme.md s podrobným popisem struktury a instrukcemi pro spuštění projektu.

API webové části je poměrně jednoduché, skládá se ze 6 rout:

  • /ping — pro kontrolu dostupnosti;
  • routy pro registraci, autorizaci, deautorizaci a získání autorizovaného uživatele;
  • routa pro odesílání emailu, která přidává úlohu do fronty Celery.

Celery část je ještě jednodušší, existuje tam pouze jedna úloha send_mail_task.

Ve složce /conf jsou zde dvě podsložky:

  • docker s dvěma Docker soubory (base.dockerfile pro sestavení seldom měněného základního obrazu a Dockerfile pro hlavní sestavy);
  • .env_files — se soubory proměnných pro různé prostředí.

V kořeni projektu se nacházejí čtyři soubory docker-compose:

  • docker-compose.local.db.yml pro spuštění lokální databáze pro vývoj;
  • docker-compose.local.workers.yml pro lokální spuštění workeru, databáze, Redis a RabbitMQ;
  • docker-compose.test.yml pro provádění testů při nasazení;
  • docker-compose.yml pro nasazení.

A poslední zajímavá složka pro nás — .ci-cd. Obsahuje shell skripty pro nasazení:

  • deploy.sh — spuštění migrace a nasazení. Spouští se na serveru po sestavení a provedení testů v Github Actions;
  • rollback.sh — vrácení kontejnerů na předchozí verzi sestavení;
  • curl_tg.sh — odesílání upozornění na nasazení do Telegramu.

Frontend na Angularu

Repozitář s frontendem je výrazně jednodušší než backendový. Frontend se skládá ze tří stránek:

  • Hlavní stránka s formulářem pro odesílání emailu a tlačítkem pro odhlášení.
  • Přihlašovací stránka.
  • Registrační stránka.

Hlavní stránka vypadá skromně:

CI/CD v Github Actions pro projekt na Flasku a Angularu.
V kořenovém adresáři jsou dva soubory Dockerfile a docker-compose.yml, stejně jako známá složka .ci-cd s o něco menším počtem skriptů než v backendovém repozitáři (byly odstraněny skripty pro spuštění testů).

Založení projektu v Plesk

Začneme s nastavením Plesk a vytvořením předplatného pro naši stránku.

Instalace rozšíření

V Plesk budeme potřebovat čtyři rozšíření:

  • Docker pro správu a vizuální zobrazení stavu kontejnerů v administraci Plesk;
  • Git pro nastavení kroku nasazení na serveru;
  • Let's Encrypt pro generování (a automatické obnovování) bezplatných TLS certifikátů;
  • Firewall pro nastavení filtrování příchozího provozu.

Instalovat je lze přes administraci Plesk v sekci Rozšíření:

CI/CD v Github Actions pro projekt na Flasku a Angularu.
Podrobnou konfiguraci rozšíření nebudeme zkoumat, pro naše demo účely budou vyhovovat výchozí nastavení.

Vytvoření předplatného a webové stránky

Dále potřebujeme vytvořit předplatné pro naši stránku helloworld.ru a přidat tam subdoménu dev.helloworld.ru.

  1. Vytváříme předplatné pro doménu helloworld.ru a uvádíme uživatelské jméno a heslo pro systémového uživatele:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.
    Dole na stránce zaškrtneme Secure the domain with Let’s Encrypt, pokud chceme nastavit HTTPS pro stránku:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  2. Dále v tomto předplatném vytváříme subdoménu dev.helloworld.ru (pro kterou lze rovněž vydat bezplatný TLS certifikát):

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

Instalace serverových komponentů

Máme k dispozici server s OS Debian Stretch 9.12 a nainstalovanou řídicí panely Plesk Obsidian 18.0.27.

Musíme nainstalovat a nastavit pro náš projekt:

  • PostgreSQL (v našem případě bude jeden server se dvěma databázemi pro dev a prod prostředí).
  • RabbitMQ (to samé, jeden instance s různými vhosts pro prostředí).
  • Dva instance Redis (pro dev a prod prostředí).
  • Docker Registry (pro místní ukládání sestavených Docker obrazů).
  • UI rozhraní pro Docker registry.

PostgreSQL

S Plesk už je dodávaná databáze PostgreSQL, avšak ne v nejnovější verzi (k datu psaní tohoto článku Plesk Obsidian podporoval Postgres verzí 8.4–10.8). My však chceme pro naši aplikaci nejnovější verzi (12.3 k datu psaní tohoto článku), takže ji nainstalujeme ručně.

Na internetu je spousta podrobných návodů na instalaci Postgres na Debianu (příklad), takže je nebudu podrobně popisovat, pouze uvedu příkazy:

wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'

sudo apt-get update
sudo apt-get install postgresql postgresql-contrib

Vzhledem k tomu, že PostgreSQL má průměrně nastavené výchozí hodnoty, je nezbytné upravit konfiguraci. S tím nám pomůže kalkulačka: je třeba zadat parametry svého serveru a nahradit nastavení v souboru /etc/postgresql/12/main/postgresql.confnávrhy. Je třeba poznamenat, že podobné kalkulačky nejsou stříbrnou kulkou a databázi je třeba jemněji ladit podle vašeho hardwaru, aplikace a složitosti dotazů. Ale pro začátek je to dostatečné.

Kromě nastavení navržených kalkulačkou měníme také v postgresql.confvýchozí port 5432 na jiný (v našem příkladu — 53983).

Po změně konfiguračního souboru restartujeme postgresql-server příkazem:

service postgresql restart

Nainstalovali jsme a nastavili PostgreSQL. Nyní vytvoříme databáze, uživatele pro dev- a prod- prostředí a udělíme uživatelům práva na správu databází:

$ su - postgres
postgres:~$ create database hw_dev_db_name;
CREATE DATABASE
postgres:~$ create user hw_dev_db_user with password 'hw_dev_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_dev_db_name to hw_dev_db_user;
GRANT
postgres:~$ create database hw_prod_db_name;
CREATE DATABASE
postgres:~$ create user hw_prod_db_user with password 'hw_prod_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_prod_db_name to hw_prod_db_user;
GRANT

RabbitMQ

Přejdeme k instalaci RabbitMQ — zprostředkovatele zpráv pro Celery. Na Debianu se instaluje docela jednoduše:

wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
sudo dpkg -i erlang-solutions_1.0_all.deb

sudo apt-get update
sudo apt-get install erlang erlang-nox

sudo add-apt-repository 'deb http://www.rabbitmq.com/debian/ testing main'
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -

sudo apt-get update
sudo apt-get install rabbitmq-server

Po instalaci musíme vytvořit vhosts, uživatele a udělit potřebná práva:

sudo rabbitmqctl add_user hw_dev_amqp_user hw_dev_amqp_password 
sudo rabbitmqctl set_user_tags hw_dev_amqp_user administrator
sudo rabbitmqctl add_vhost hw_dev_vhost
sudo rabbitmqctl set_permissions -p hw_dev_vhost hw_dev_amqp_user ".*" ".*" ".*"

sudo rabbitmqctl add_user hw_prod_amqp_user hw_prod_amqp_password 
sudo rabbitmqctl set_user_tags hw_prod_amqp_user administrator
sudo rabbitmqctl add_vhost hw_prod_vhost
sudo rabbitmqctl set_permissions -p hw_prod_vhost hw_prod_amqp_user ".*" ".*" ".*"

Redis

Nyní nainstalujeme a nastavíme poslední komponentu pro naši aplikaci — Redis. Bude použit jako backend pro ukládání výsledků úloh Celery.

Zvedneme dva Docker kontejnery s Redis pro dev- a prod- prostředí pomocí rozšíření Docker pro Plesk.

  1. Přejdeme do Plesku, otevřeme sekci Rozšíření, vyhledáme rozšíření Docker a nainstalujeme ho (potřebujeme bezplatnou verzi):

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  2. Přejdeme do nainstalovaného rozšíření a najdeme přes vyhledávání obraz redis bitnami a nainstalujeme poslední verzi:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  3. Přejdeme do staženého kontejneru a upravíme konfiguraci: nastavíme port, maximální přidělenou velikost RAM, heslo v proměnných prostředí a namontujeme svazek:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  4. Provádíme kroky 2-3 pro prod-kontejner, pouze měníme parametry: port, heslo, velikost RAM a cestu ke složce svazku na serveru:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

Docker Registry

Kromě základních služeb by bylo dobré na server nainstalovat vlastní repozitář Docker obrazů. Naštěstí je místo na serverech dnes dost levné (určitě levnější než předplatné na DockerHub) a proces instalace soukromého repozitáře je velmi jednoduchý.

Chceme, aby byly nainstalovány:

K tomu:

  1. V Plesku vytvoříme dva subdomény v našem předplatném: docker.helloworld.ru a docker-ui.helloworld.ru, a nastavíme pro ně certifikáty Let’s Encrypt.
  2. Do složky subdomény docker.helloworld.ru přidáme soubor docker-compose.yml s tímto obsahem:
    version: "3"
    
    services:
      docker-registry:
        image: "registry:2"
        restart: always
        ports:
          - "53985:5000"
        environment:
          REGISTRY_AUTH: htpasswd
          REGISTRY_AUTH_HTPASSWD_REALM: basic-realm
          REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd
          REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
        volumes:
          - ./docker-registry.htpasswd:/auth/.htpasswd
          - ./data:/data
    
      docker-registry-ui:
        image: konradkleine/docker-registry-frontend:v2
        restart: always
        ports:
          - "53986:80"
        environment:
          VIRTUAL_HOST: '*, https://*'
          ENV_DOCKER_REGISTRY_HOST: 'docker-registry'
          ENV_DOCKER_REGISTRY_PORT: 5000
        links:
          - 'docker-registry'
    

  3. Přes SSH vygenerujeme soubor .htpasswd pro Basic autorizaci v Docker repozitáři:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Sestavíme a spustíme kontejnery:
    docker-compose up -d
  5. A je potřeba přesměrovat Nginx na naše kontejnery. To lze provést přes Plesk.

Následující akce je potřeba provést pro subdomény docker.helloworld.ru a docker-ui.helloworld.ru:

V sekci Dev Tools naší stránky se dostaneme do Docker Proxy Rules:

CI/CD v Github Actions pro projekt na Flasku a Angularu.
A přidáme pravidlo pro procházení příchozího provozu do našeho kontejneru:

CI/CD v Github Actions pro projekt na Flasku a Angularu.

  1. Zkontrolujeme, že se můžeme autorizovat v našem kontejneru z lokálního počítače:
    $ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password
    UPOZORNĚNÍ! Použití --password přes CLI je nepraktické. Použijte --password-stdin.
    Úspěšné přihlášení
  2. Také zkontrolujeme funkci subdomény docker-ui.helloworld.ru:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.
    Když kliknete na procházet repozitáře, prohlížeč otevře okno pro přihlášení, kde budete muset zadat uživatelské jméno a heslo pro repozitář. Poté budete přesměrováni na stránku se seznamem repozitářů (prozatím bude prázdná):

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

Otevřete porty ve Firewallu Plesk

Po instalaci a nastavení komponent musíme otevřít porty, aby byly komponenty přístupné z Docker kontejnerů a z vnější sítě.

Podíváme se, jak to udělat, na příkladu rozšíření Firewall pro Plesk, které jsme nainstalovali dříve.

  1. Přejdeme do Nástroje & Nastavení > Nastavení > Firewall:
    CI/CD v Github Actions pro projekt na Flasku a Angularu.
  2. Přejdeme do Upravit pravidla Firewall Plesk > Přidat vlastní pravidlo a otevření následujících TCP portů pro podsíť Docker (172.0.0.0/8):
    RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis: 32785, 32786

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  3. Dále přidáme pravidlo, které otevře porty PostgreSQL a management panelu RabbitMQ pro vnější svět:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  4. Aplikujte pravidla pomocí tlačítka Aplikovat změny:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

Nastavení CI/CD v Github Actions

Přistoupíme k nejzajímavější části — nastavení pipeline kontinuální integrace a dodání našeho projektu na server.

Tato pipeline se bude skládat ze dvou částí:

  • sestavení obrazu a spuštění testů (pro backend) — na straně Github;
  • spuštění migrací (pro backend) a nasazení kontejnerů — na serveru.

Nasazení v Plesk

Nejprve se podíváme na druhý bod (protože od něj závisí první).

Proces nasazení nastavíme pomocí rozšíření Git pro Plesk.

Uvažujme příklad s produkčním prostředím pro Backend repozitář.

  1. Přejdeme do odběru našeho webu Helloworld a přejdeme do podsekce Git:

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  2. Vložíme do pole „Remote Git repository“ odkaz na náš Github repozitář a změníme výchozí složku httpdocs na jinou (například, /httpdocs/hw_back):

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  3. Zkopírujte SSH veřejný klíč z předchozího kroku a přidejte ho do nastavení Github.
  4. Stiskněte OK na obrazovce v bodě 2, poté budete přesměrováni na stránku repozitáře v Plesk. Nyní musíme nastavit aktualizaci repozitáře při commitech do větve master. K tomu přejdeme do Nastavení repozitáře a uložíme hodnotu Webhook URL (bude potřeba později při nastavování Github Actions):

    CI/CD v Github Actions pro projekt na Flasku a Angularu.

  5. Na obrazovce z předchozího bodu do pole Actions zadáme skript pro spuštění nasazení:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    kde:

    {REPOSITORY_ABSOLUTE_PATH} — cesta k adresáři produkčního backend repozitáře na serveru;
    {ENV} — prostředí (dev/production), v našem případě prod;
    {DOCKER_REGISTRY_HOST} — host našich docker repozitářů
    {TG_BOT_TOKEN} — token Telegram bota;
    {TG_CHAT_ID} — ID chatu/kanálu pro zasílání oznámení.

    Příklad skriptu:

    cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
    .ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
  6. Přidáváme uživatele z našeho předplatného do skupiny Docker (aby mohl spravovat kontejnery):
    sudo usermod -aG docker helloworld_admin

Vývojové prostředí pro backend-repozitář a frontend se nastavuje obdobně.

Pipeline nasazení v Github Actions

Přecházíme k nastavení první části našeho CI/CD pipeline v Github Actions.

Backend plánovali udělat na Linuxu. Backend interaguje s DB, načítá potřebný seznam privilegií a poté, v závislosti na tom, jaká privilegium má autorizovaný uživatel, poskytuje přístup k podepisování finančních dokumentů a jejich zasílání k realizaci, nebo generaci nějaké zprávy.

Pipeline je popsána v souboru deploy.yml.

Než se na něj podíváme, vyplníme v Github potřebné tajné proměnné. K tomu přejdeme do Nastavení -> Tajné:

  • DOCKER_REGISTRY — host našich Docker-repozitářů (docker.helloworld.ru);
  • DOCKER_LOGIN — přihlašovací jméno k Docker-repozitáři;
  • DOCKER_PASSWORD — heslo k němu;
  • DEPLOY_HOST — host, na kterém je dostupné administrativní rozhraní Plesk (např. helloworld.ru:8443 nebo 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN — token pro nasazení do prod-repozitáře na serveru (dostali jsme jej v Nasazení v Plesk bod 4);
  • DEPLOY_BACK_DEV_TOKEN — token pro nasazení do dev-repozitáře na serveru.

Proces nasazení je jednoduchý a skládá se ze tří hlavních kroků:

  • sestavení a publikace obrazu v našem repozitáři;
  • spuštění testů v kontejneru na základě čerstvě sestaveného obrazu;
  • nasazení do požadovaného prostředí v závislosti na větvi (dev/master).

Frontend

Soubor deploy.yml pro front-repozitář se příliš neliší od backendového. Chybí v něm krok se spuštěním testů a mění se názvy tokenů pro nasazení. Tajné proměnné pro front-repozitář je mimochodem třeba vyplnit zvlášť.

Nastavení webu

Proxy provozu přes Nginx

No, a jsme na konci. Zbývá pouze nastavit proxy příchozího a odchozího provozu do našeho kontejneru přes Nginx. Tento proces jsme již probrali v bodě 5 nastavení Docker Registry. Totéž je třeba zopakovat pro backend a frontend v dev a prod prostředích.

Připojím snímky nastavení.

Backend plánovali udělat na Linuxu. Backend interaguje s DB, načítá potřebný seznam privilegií a poté, v závislosti na tom, jaká privilegium má autorizovaný uživatel, poskytuje přístup k podepisování finančních dokumentů a jejich zasílání k realizaci, nebo generaci nějaké zprávy.

CI/CD v Github Actions pro projekt na Flasku a Angularu.

Frontend

CI/CD v Github Actions pro projekt na Flasku a Angularu.
Důležité upřesnění. Do frontendového kontejneru budou proxy všechny URL, kromě těch, které začínají na /api/ — ty budou proxy do backendového kontejneru (proto v backendovém kontejneru by měly všechny zpracovatele začínat na /api/).

Závěry

Nyní by měl být náš web dostupný na adresách helloworld.ru a dev.helloworld.ru (prod a dev prostředí odpovídající).

Celkově jsme se naučili, jak připravit jednoduchou aplikaci na Flask a Angular a nastavit v Github Actions pipeline pro její nasazení na serveru řízeném Pleskem.

Zopakuji odkazy na repozitáře s kódem: backend, frontend.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster