CI/CD ar Github Actions Flask+Angular projektam

CI/CD ar Github Actions Flask+Angular projektam
Šajā rakstā es dalīšos ar savu pieredzi CI/CD iestatīšanā, izmantojot Plesk vadības paneli un Github Actions. Šodien mācīsimies izvietot vienkāršu projektu ar nosaukumu „Helloworld”. Tas ir izstrādāts Python ietvarā Flask, ar uzdevumu izpildītājiem Celery un frontendā Angular 8.

Saite uz repozitorijiem: backend, frontend.

Pirmajā raksta daļā mēs apskatīsim mūsu projektu un tā komponentes. Otrajā — izpētīsim, kā iestatīt Plesk un instalēt nepieciešamos paplašinājumus un komponentus (DB, RabbitMQ, Redis, Docker u.t.t.).

Trešajā daļā mēs, galu galā, noskaidrosim, kā iestatīt pipeline mūsu projekta ievietošanai serverī dev- un prod-vidēs. Un pēc tam palaidīsim vietni uz servera.

Un jā, aizmirsu sevi iepazīstināt. Mani sauc Oļegs Borzovs, es esmu fullstack izstrādātājs CRM komandā, kas strādā ar hipotekāro kredītu menedžeriem Domklikā.

Projekta apskats

Vispirms apskatīsim divus projekta repozitorijus — backend un frontend — un ātri pāriesim cauri kodam.

Backend daļa: Flask+Celery

Backend daļai es izmantoju diezgan populāro kombināciju starp Python izstrādātājiem: Flask ietvars (API) un Celery (uzdevumu rinda). ORM ir SQLAlchemy. Migrācijām izmanto Alembic. JSON validācijai rokas rezultātos — Marshmallow.

No repozitorijā ir Readme.md fails ar detalizētu struktūras aprakstu un instrukcijām projekta palaišanai.

API web daļai ir diezgan vienkāršs, sastāv no 6 rokas:

  • /ping — pieejamības pārbaudei;
  • roka reģistrācijai, autorizācijai, deautorizācijai un autorizētā lietotāja iegūšanai;
  • roka e-pasta sūtīšanai, kas pievieno uzdevumu Celery rindai.

Celery daļa vēl vienkāršāka, tur ir tikai viens uzdevums send_mail_task.

Mapē /conf ir divas apakšmapes:

  • docker ar diviem Docker failiem (base.dockerfile lai izveidotu reti mainīgu pamata attēlu un Dockerfile galvenajām kompilācijām);
  • .env_files — ar mainīgo apkārtējo failiem dažādām vidēm.

Projekta saknē atrodas četri faila docker-compose:

  • docker-compose.local.db.yml lokālās DB uzstādīšanai izstrādei;
  • docker-compose.local.workers.yml lokālo darbinieka, DB, Redis un RabbitMQ uzstādīšanai;
  • docker-compose.test.yml testu veikšanai izvietošanas laikā;
  • docker-compose.yml izvietošanai.

Un pēdējā interesantā mape — .ci-cd. Tajā atrodas shell skripti izvietošanai:

  • deploy.sh — migrācijas un izvietošanas palaišana. Sākas serverī pēc kompilācijas un testu veikšanas Github Actions;
  • rollback.sh — konteineru atgriešana iepriekšējā versijā;
  • curl_tg.sh — paziņojumu sūtīšana par izvietošanu Telegram.

Priekšējais plāns uz Angular

Repozitorijs ar priekšpusi kā ļoti vienkāršs aizmugures plāns. Priekšpuse sastāv no trim lapām:

  • Galvenā lapa ar veidlapu e-pasta nosūtīšanai un izejas pogu.
  • Ieejas lapa.
  • Reģistrācijas lapa.

Galvenā lapa izskatās atturīgi:

CI/CD ar Github Actions Flask+Angular projektam
Pamatā atrodas divas failu Dockerfile un docker-compose.yml, kā arī pazīstamā mums mapa .ci-cd ar nedaudz mazāku skriptu skaitu nekā aizmugures plānā (noņemti skripti testu palaišanai).

Izveidojam projektu Pleskā

Sāksim ar Plesk iestatīšanu un abonementa izveidi mūsu vietnei.

Paplašinājumu uzstādīšana

Pleskā mums būs nepieciešami četri paplašinājumi:

  • Docker lai vadītu un vizuāli attēlotu konteineru stāvokli Plesk administrācijā;
  • Git lai konfigurētu izvietošanas soli serverī;
  • Let's Encrypt lai ģenerētu (un automātiski atjaunotu) bezmaksas TLS sertifikātus;
  • Ugunsmūris lai konfigurētu ienākošā trafika filtrēšanu.

Iespējams tos uzstādīt caur Plesk administrāciju sadaļā Paplašinājumi:

CI/CD ar Github Actions Flask+Angular projektam
Detālākas paplašinājumu iestatīšanas mēs neizskatīsim, mūsu demonstrācijas mērķiem derēs noklusējuma iestatījumi.

Abonementa un vietnes izveide

Tālāk mums jāizveido abonements mūsu vietnei helloworld.ru un jāpievieno apakšdomēns dev.helloworld.ru.

  1. Izveidojam abonementu domēnam helloworld.ru un norādām sistēmas lietotāja lietotājvārdu-paroli:

    CI/CD ar Github Actions Flask+Angular projektam
    Lapas apakšdaļā atzīmējam izvēles rūtiņu Secure the domain with Let’s Encrypt, ja vēlamies iestatīt HTTPS vietnei:

    CI/CD ar Github Actions Flask+Angular projektam

  2. Tālāk šajā abonementā izveidojam apakšdomēnu dev.helloworld.ru (kuram arī var izsniegt bezmaksas TLS sertifikātu):

    CI/CD ar Github Actions Flask+Angular projektam

Servera komponentu uzstādīšana

Mums ir serveris ar OS Debian Stretch 9.12 un uzstādītu vadības paneli Plesk Obsidian 18.0.27.

Mums jāuzstāda un jākonfigurē mūsu projektam:

  • PostgreSQL (mūsu gadījumā būs viens serveris ar divām DB dev- un prod-vidēm).
  • RabbitMQ (tas pats, viens instants ar dažādiem vhosts vidēm).
  • Divi Redis instanti (dev- un prod-vidēm).
  • Docker Registry (lokālas saglabāšanas mērķiem konstruētiem Docker attēliem).
  • UI interfeiss Docker registry.

PostgreSQL

Kopā ar Plesk jau ietilpst SGBD PostgreSQL, tomēr ne pati jaunākā versija (raksta laikā Plesk Obsidian atbalstīja Postgres versijas 8.4–10.8). Mēs vēlamies mūsu lietojumam pašlaik jaunāko versiju (12.3 raksta laikā), tāpēc uzstādīsim to manuāli.

Interneta telpā ir daudz detalizētu instrukciju par PostgreSQL uzstādīšanu Debian (piemērs), tāpēc detalizēti tās neaprakstīšu, vienkārši norādīšu komandas:

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

Ņemot vērā to, ka PostgreSQL noklusējuma iestatījumi ir diezgan viduvēji, ir nepieciešams pielāgot konfigurāciju. Mums šajā palīdzēs kalkulators: jāievada sava servera parametri un jānomaina iestatījumi failā /etc/postgresql/12/main/postgresql.confuz ieteiktajiem. Šeit jānorāda, ka šādi kalkulatori nav brīnumlīdzeklis, un datubāze jāoptimizē precīzāk, ņemot vērā jūsu aparatūru, lietojumprogrammu un vaicājumu sarežģītību. Bet sākumam šis ir pietiekami.

Papildus kalkulatora ieteiktajiem iestatījumiem mēs arī mainām postgresql.confnoklusējuma portu 5432 uz citu (mūsu piemērā — 53983).

Pēc konfigurācijas faila izmaiņām restartējam postgresql-server ar komandu:

service postgresql restart

Mēs esam instalējuši un konfigurējuši PostgreSQL. Tagad izveidosim datubāzi, lietotājus dev- un prod-vidēm un piešķirsim lietotājiem tiesības pārvaldīt datubāzi:

$ 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āriesim pie RabbitMQ — ziņojumu starpnieka uzstādīšanas Celery. To uzstādīt Debian ir diezgan vienkārši:

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

Pēc uzstādīšanas mums jāizveido vhosts, lietotāji un jāpiešķir nepieciešamās tiesības:

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

Tagad uzstādīsim un konfigurēsim pēdējo komponentu mūsu lietojumprogrammai — Redis. To izmantosim kā backend rezultātu uzglabāšanai Celery uzdevumiem.

Mēs uzsāksim divus Docker konteinerus ar Redis dev- un prod-vidēm, izmantojot paplašinājumu Docker Plesk.

  1. Ienākam Pleskā, ejam uz sadaļu Paplašinājumi, meklējam paplašinājumu Docker un instalējam to (mums nepieciešama bezmaksas versija):

    CI/CD ar Github Actions Flask+Angular projektam

  2. Pārejām uz instalēto paplašinājumu, atrodam caur meklēšanu attēlu redis bitnami un uzstādām jaunāko versiju:

    CI/CD ar Github Actions Flask+Angular projektam

  3. Ienākam lejupielādētajā konteinerā un pielāgojam konfigurāciju: norādām portu, maksimālo piešķirto RAM lielumu, paroli mainīgajos, un montējam apjomu:

    CI/CD ar Github Actions Flask+Angular projektam

  4. Izpildām soļus 2-3 prod-konteineram, tikai iestatījumos mainām parametrus: portu, paroli, RAM lielumu un ceļu uz mapes apjomu serverī:

    CI/CD ar Github Actions Flask+Angular projektam

Docker Registry

Papildus pamata pakalpojumiem nebūtu slikti uzstādīt uz servera savu Docker attēlu repozitoriju. Galu galā, vieta serveros tagad ir diezgan lēta (noteikti lētāk par DockerHub abonementu), un privātā repozitorija uzstādīšana ir ļoti vienkārša.

Mēs vēlamies, lai mums būtu uzstādīts:

Tam:

  1. Izveidosim Pleskā divus apakšdomēnus mūsu abonementā: docker.helloworld.lv un docker-ui.helloworld.lv, un iestatīsim tiem Let’s Encrypt sertifikātus.
  2. Apakšdomēna docker.helloworld.lv mapē pievienosim failu docker-compose.yml ar šādu saturu:
    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. Izmantojot SSH, izveidosim failu .htpasswd, lai veiktu pamata autorizāciju Docker repositārijā:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Savilksim un uzsāksim konteinerus:
    docker-compose up -d
  5. Un jāpārvirza Nginx uz mūsu konteineriem. To var izdarīt caur Plesk.

Nākamās darbības jādara apakšdomēniem docker.helloworld.lv un docker-ui.helloworld.lv:

Sadaļā Dev Tools mūsu mājas lapā ejam uz Docker Proxy Rules:

CI/CD ar Github Actions Flask+Angular projektam
Un pievienojam noteikumu ieejas satiksmes pārsūknēšanai uz mūsu konteineru:

CI/CD ar Github Actions Flask+Angular projektam

  1. Pārbaudām, vai varam autorizēties mūsu konteinerā no lokālās mašīnas:
    $ docker login docker.helloworld.lv -u hw_docker_admin -p hw_docker_password
    WARNING! Using --password via the CLI is insecure. Use --password-stdin.
    Login Succeeded
  2. Tāpat pārbaudīsim apakšdomēna docker-ui.helloworld.lv darbību:

    CI/CD ar Github Actions Flask+Angular projektam
    Noklikšķinot uz Browse repositories, pārlūkprogramma parādīs autentifikācijas logu, kurā jāievada pieslēgšanās vārds un parole, lai piekļūtu repozitorijam. Pēc tam mūs novirzīs uz repozitoriju saraksta lapu (jūsu vēl būs tukša):

    CI/CD ar Github Actions Flask+Angular projektam

Atveram portus Plesk ugunsmūrī

Pēc komponentu instalēšanas un iestatīšanas mums jāatver porti, lai komponenti būtu pieejami no Docker konteinera un ārējās tīkla.

Apskatīsim, kā to izdarīt, ņemot vērā iepriekš instalētā Plesk ugunsmūra paplašinājuma piemēru.

  1. Pārejam uz Tools & Settings > Settings > Firewall:
    CI/CD ar Github Actions Flask+Angular projektam
  2. Pārejam uz Modify Plesk Firewall Rules > Add Custom Rule un atveram šādus TCP portus Docker apakštīklam (172.0.0.0/8):
    RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis: 32785, 32786

    CI/CD ar Github Actions Flask+Angular projektam

  3. Tāpat pievienosim noteikumu, kas atvērs ārējai pasaulei PostgreSQL un RabbitMQ pārvaldības paneļa portus:

    CI/CD ar Github Actions Flask+Angular projektam

  4. Piemērojam noteikumus, izmantojot pogu Apply Changes:

    CI/CD ar Github Actions Flask+Angular projektam

CI/CD konfigurācija Github Actions

Sāksim ar pašu interesantāko daļu — mūsu projekta nepārtrauktās integrācijas un piegādes līnijas iestatīšanu līdz serverim.

Šī līnija sastāvēs no divām daļām:

  • attēla izveide un testu izpilde (aizmugurē) — Github pusē;
  • migrāciju izpilde (aizmugurē) un konteineru izvietošana — serverī.

Izvietošana Plesk

Sāksim vispirms ar otro punktu (jo tas ietekmē pirmo).

Izvietošanas procesu mēs konfigurēsim, izmantojot Git paplašinājumu Plesk.

APSkatīsim piemēru ar Prod vidi aizmugures repozitorijam.

  1. Ieejam mūsu vietnes Helloworld abonementā un pārejam uz apakšsadaļu Git:

    CI/CD ar Github Actions Flask+Angular projektam

  2. Ievietojam laukā "Remote Git repository" saiti uz mūsu Github repozitoriju un mainām noklusējuma mapi httpdocs uz citu (piemēram, /httpdocs/hw_back):

    CI/CD ar Github Actions Flask+Angular projektam

  3. Kopējam SSH Public key no iepriekšējā posma un pievienojam to Github iestatījumos.
  4. Noklikšķinām uz OK ekrānā punktā 2, pēc tam mūs novirza uz repozitorija lapu Plesk. Tagad mums jāsakārto repozitorija atjaunināšana, ja tiek veikti komandi pie galvenās filiāles. Tam pārejam uz Repository Settings un saglabājam vērtību Webhook URL (tas būs nepieciešams vēlāk, konfigurējot Github Actions):

    CI/CD ar Github Actions Flask+Angular projektam

  5. Laukā Actions ekrānā no iepriekšējā punkta ievadām skriptu izvietošanai:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    kur:

    {REPOSITORY_ABSOLUTE_PATH} — ceļš uz prod aizmugures repozitorija mapi serverī;
    {ENV} — vide (dev/prod), mūsu gadījumā prod;
    {DOCKER_REGISTRY_HOST} — mūsu docker repozitorija hosta;
    {TG_BOT_TOKEN} — Telegram bota tokens;
    {TG_CHAT_ID} — čata/kanāla ID, lai nosūtītu paziņojumus.

    Skriptu piemērs:

    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. Pievienojam lietotāju no mūsu abonementa Docker grupai (lai viņš varētu pārvaldīt konteinerus):
    sudo usermod -aG docker helloworld_admin

Izstrādes vide backend repozitorijam un frontend tiek iestatīta līdzīgi.

Palaidnes pipelines Github Actions

Pārejiet uz pirmās daļas konfigurāciju mūsu CI/CD pipeline Github Actions.

Backend

Pipelins tiek aprakstīts failā deploy.yml.

Bet pirms to izskatām, aizpildīsim Github nepieciešamās Secret mainīgās. Lai to izdarītu, dodamies uz Iestatījumi -> Slepenie:

  • DOCKER_REGISTRY — mūsu Docker repozitorija hosta (docker.helloworld.ru);
  • DOCKER_LOGIN — pieteikšanās Docker repozitorijam;
  • DOCKER_PASSWORD — parole tam;
  • DEPLOY_HOST — host, kur pieejama Plesk administrācija (piemērs: helloworld.ru:8443 vai 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN — tokenam produkta repozitorijā serverī (mēs to saņēmām sadaļā Izvietošana Plesk p. 4);
  • DEPLOY_BACK_DEV_TOKEN — tokenam izstrādes repozitorijā serverī.

Izvietošanas process ir vienkāršs un sastāv no trim galvenajiem soļiem:

  • attēla būvēšana un publicēšana mūsu repozitorijā;
  • testu palaišana konteinerā, pamatojoties uz jaunizveidoto attēlu;
  • izvietošana vajadzīgajā vidē atkarībā no zara (dev/master).

Frontend

Fails deploy.yml frontend repozitorijam mazliet atšķiras no backend. Tajā nav soļa ar testu palaišanu un tiek mainīti tokenu nosaukumi izvietošanai. Slepenie dati frontend repozitorijam, starp citu, jāaizpilda atsevišķi.

Mājaslapas konfigurācija

Tīkla trafika pārsūtīšana caur Nginx

Nu, mēs esam nonākuši pie beigām. Atlikusi tikai ienākošā un izejošā trafika pārsūtīšana mūsu konteinerā caur Nginx. Šo procesu mēs jau apspriedām punktā 5 Docker Registry konfigurācijā. To pašu jāatkārto backend un frontend daļai izstrādes un produkta vidēs.

Iekļaušu ekrānuzņēmumus ar iestatījumiem.

Backend

CI/CD ar Github Actions Flask+Angular projektam

Frontend

CI/CD ar Github Actions Flask+Angular projektam
Svarīgs precizējums. Frontend konteinerā tiks pārsūtīti visi URL, izņemot tos, kas sākas ar /api/ — tie tiks pārsūtīti uz backend konteineru (tāpēc backend konteinerā visiem apstrādātājiem jāuzsāk ar /api/).

Secinājumi

Tagad mūsu mājaslapa jāpiekļūst adresēm helloworld.ru un dev.helloworld.ru (atbilstoši produkta un izstrādes vidēm).

Kopumā mēs uzzinājām, kā sagatavot vienkāršu lietojumprogrammu uz Flask un Angular un konfigurēt Github Actions pipeline tās izvietošanai serverī, kuru pārvalda Plesk.

Atkārtošu saites uz repozitorijiem ar kodu: backend, frontend.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster