CI/CD în Acțiuni Github pentru un proiect Flask+Angular
În acest articol, voi împărtăși experiența mea de configurare CI/CD utilizând panoul de control Plesk și Github Actions. Astăzi vom învăța cum să implementăm un proiect simplu cu numele simplu „Helloworld”. Este scris în cadrul Flask Python, cu lucrători de țelină și un front-end Angular 8.
În prima parte a articolului, vom analiza proiectul nostru și părțile sale. În al doilea, ne vom da seama cum să setăm Plesk și să instalăm extensiile și componentele necesare (DB, RabbitMQ, Redis, Docker etc.).
În cea de-a treia parte, vom descoperi în sfârșit cum să configuram o conductă pentru implementarea proiectului nostru pe un server într-un mediu de dezvoltare și producție. Și apoi vom lansa site-ul pe server.
Și da, am uitat să mă prezint. Numele meu este Oleg Borzov, sunt dezvoltator fullstack în echipa CRM pentru managerii de credite ipotecare de la Domclick.
Prezentare generală a proiectului
Mai întâi, să ne uităm la două depozite de proiecte - backend și front - și să trecem peste cod.
Backend: balon + țelină
Pentru partea din spate, am luat o grămadă care este destul de populară printre dezvoltatorii Python: framework-ul Flask (pentru API) și Celery (pentru coada de activități). SQLAchemy este folosit ca ORM. Alambicul este folosit pentru migrații. Pentru validarea JSON în mânere - Marshmallow.
В depozite există un fișier Readme.md cu o descriere detaliată a structurii și instrucțiuni pentru rularea proiectului.
API Web Part destul de simplu, constă din 6 stilouri:
/ping - pentru a verifica disponibilitatea;
manere pentru înregistrare, autorizare, dezautorizare și obținerea unui utilizator autorizat;
un handle de e-mail care pune o sarcină în coada de țelină.
Parte de țelină si mai usor, exista o singura problema send_mail_task.
docker cu două Dockerfile (base.dockerfile pentru a construi o imagine de bază care se schimbă rar și Dockerfile pentru ansambluri principale);
.env_files - cu fișiere cu variabile de mediu pentru diferite medii.
Există patru fișiere docker-compose la rădăcina proiectului:
docker-compose.local.db.yml să creeze o bază de date locală pentru dezvoltare;
docker-compose.local.workers.yml pentru ridicarea locală a lucrătorului, baza de date, Redis și RabbitMQ;
docker-compose.test.yml pentru a rula teste în timpul implementării;
docker-compose.yml pentru desfășurare.
Și ultimul folder care ne interesează - .ci-cd. Conține scripturi shell pentru implementare:
deploy.sh — lansarea migrației și implementării. Rulează pe server după construirea și rularea testelor în Github Actions;
rollback.sh - derularea containerelor la versiunea anterioară a ansamblului;
curl_tg.sh - trimiterea notificărilor de implementare către Telegram.
Frontend pe Angular
Depozit cu față mult mai simplu decât al lui Beck. Fața este formată din trei pagini:
Pagina principală cu un formular pentru trimiterea e-mailului și un buton de ieșire.
Pagina de logare.
Pagina de înregistrare.
Pagina principală pare ascetică:
Există două fișiere la rădăcină Dockerfile и docker-compose.yml, precum și folderul familiar .ci-cd cu puțin mai puține scripturi decât în depozitul din spate (scripturi eliminate pentru rularea testelor).
Pornirea unui proiect în Plesk
Să începem prin a configura Plesk și a crea un abonament pentru site-ul nostru.
Instalarea extensiilor
În Plesk, avem nevoie de patru extensii:
Docker pentru a gestiona și afișa vizual starea containerelor în panoul de administrare Plesk;
Git pentru a configura pasul de implementare pe server;
Let's Encrypt pentru a genera (și reînnoi automat) certificate TLS gratuite;
Firewall pentru a configura filtrarea traficului de intrare.
Le puteți instala prin panoul de administrare Plesk din secțiunea Extensii:
Nu vom lua în considerare setările detaliate pentru extensii, setările implicite vor fi potrivite pentru scopurile noastre demo.
Creați un abonament și un site
Apoi, trebuie să creăm un abonament pentru site-ul nostru helloworld.ru și să adăugăm acolo subdomeniul dev.helloworld.ru.
Creați un abonament pentru domeniul helloworld.ru și specificați parola de conectare pentru utilizatorul sistemului:
Bifați caseta din partea de jos a paginii Securizează domeniul cu Let's Encryptdacă vrem să setăm HTTPS pentru site:
Apoi, în acest abonament, creați un subdomeniu dev.helloworld.ru (pentru care puteți elibera și un certificat TLS gratuit):
Instalarea componentelor serverului
Avem un server cu OS Debian Stretch 9.12 și instalat panoul de control Plesk Obsidian 18.0.27.
Trebuie să instalăm și să configurăm pentru proiectul nostru:
PostgreSQL (în cazul nostru, va exista un server cu două baze de date pentru mediile de dezvoltare și producție).
RabbitMQ (aceeași, aceeași instanță cu vhost-uri diferite pentru medii).
Două instanțe Redis (pentru medii de dezvoltare și producție).
Docker Registry (pentru stocarea locală a imaginilor Docker construite).
UI pentru registrul Docker.
PostgreSQL
Plesk vine deja cu PostgreSQL DBMS, dar nu cea mai recentă versiune (la momentul scrierii Plesk Obsidian sprijinit Versiunile Postgres 8.4–10.8). Dorim cea mai recentă versiune pentru aplicația noastră (12.3 la momentul scrierii acestui articol), așa că o vom instala manual.
Există o mulțime de instrucțiuni detaliate pentru instalarea Postgres pe Debian pe net (exemplu), așa că nu le voi descrie în detaliu, voi da doar comenzile:
Având în vedere că PostgreSQL are setări implicite destul de mediocre, este necesară corectarea configurației. Acest lucru ne va ajuta calculator: trebuie să introduceți parametrii serverului dvs. și să înlocuiți setările din fișier /etc/postgresql/12/main/postgresql.confcelor oferite. Trebuie remarcat aici că astfel de calculatoare nu sunt un glonț magic, iar baza ar trebui reglată mai precis, pe baza hardware-ului, aplicației și complexității interogărilor. Dar acest lucru este suficient pentru a începe.
Pe lângă setările propuse de calculator, mai schimbăm postgresql.confportul implicit 5432 la altul (în exemplul nostru - 53983).
După modificarea fișierului de configurare, reporniți postgresql-server cu comanda:
service postgresql restart
Am instalat și configurat PostgreSQL. Acum să creăm o bază de date, utilizatori pentru medii de dezvoltare și producție și să acordăm utilizatorilor drepturi de a gestiona baza de date:
$ 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
Iepure MQ
Să trecem la instalarea RabbitMQ, un broker de mesaje pentru Celery. Instalarea acestuia pe Debian este destul de simplă:
Acum haideți să instalăm și să configurăm ultima componentă pentru aplicația noastră - Redis. Va fi folosit ca backend pentru stocarea rezultatelor sarcinilor de țelină.
Vom ridica două containere Docker cu Redis pentru medii de dezvoltare și producție folosind extensia Docker pentru Plesk.
Mergem la Plesk, mergem la secțiunea Extensii, căutăm extensia Docker și o instalăm (avem nevoie de o versiune gratuită):
Accesați extensia instalată, găsiți imaginea prin căutare redis bitnami și instalează cea mai recentă versiune:
Intrăm în containerul descărcat și ajustăm configurația: specificăm portul, dimensiunea maximă a RAM alocată, parola în variabilele de mediu și montăm volumul:
Efectuăm pașii 2-3 pentru containerul de produse, în setări modificăm doar parametrii: port, parolă, dimensiunea RAM și calea către folderul de volum de pe server:
Registrul Docker
Pe lângă serviciile de bază, ar fi bine să vă puneți propriul depozit de imagini Docker pe server. Din fericire, spațiul pe server este acum destul de ieftin (cu siguranță mai ieftin decât un abonament DockerHub), iar procesul de configurare a unui depozit privat este foarte simplu.
Să creăm două subdomenii în Plesk în abonamentul nostru: docker.helloworld.ru și docker-ui.helloworld.ru și să configuram certificatele Let's Encrypt pentru ele.
Adăugați fișierul în folderul subdomeniului docker.helloworld.ru docker-compose.yml cu conținut ca acesta:
Și trebuie să redirecționăm Nginx către containerele noastre. Acest lucru se poate face prin Plesk.
Următorii pași trebuie efectuati pentru subdomeniile docker.helloworld.ru și docker-ui.helloworld.ru:
În secțiunea Instrumente Dev accesați site-ul nostru Reguli Docker Proxy:
Și adăugați o regulă pentru a proxy traficul de intrare în containerul nostru:
Verificăm că ne putem conecta la containerul nostru de pe mașina locală:
$ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
Să verificăm și funcționarea subdomeniului docker-ui.helloworld.ru:
Când faceți clic pe Răsfoire depozite, browserul va afișa o fereastră de autorizare în care va trebui să introduceți numele de utilizator și parola pentru depozit. După aceea, vom fi transferați pe o pagină cu o listă de depozite (deocamdată, aceasta va fi goală pentru tine):
Deschiderea porturilor în Plesk Firewall
După instalarea și configurarea componentelor, trebuie să deschidem porturi astfel încât componentele să fie accesibile din containerele Docker și din rețeaua externă.
Să vedem cum să facem acest lucru folosind extensia Firewall pentru Plesk pe care am instalat-o mai devreme.
Mergi la Instrumente și setări > Setări > Paravan de protecție:
Mergi la Modificați regulile Plesk Firewall > Adăugați o regulă personalizată și deschideți următoarele porturi TCP pentru subrețeaua Docker (172.0.0.0 / 8):
RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
Redis: 32785, 32786
Vom adăuga, de asemenea, o regulă care va deschide porturile PostgreSQL și panourile de gestionare RabbitMQ către lumea exterioară:
Să trecem la partea cea mai interesantă - crearea unei conducte de integrare continuă și livrarea proiectului nostru pe server.
Această conductă va consta din două părți:
construirea unei imagini și rularea testelor (pentru backend) - pe partea Github;
rularea migrațiilor (pentru backend) și implementarea containerelor - pe server.
Implementați pe Plesk
Să ne ocupăm mai întâi de al doilea punct (pentru că primul depinde de el).
Vom configura procesul de implementare folosind extensia Git pentru Plesk.
Luați în considerare un exemplu cu un mediu Prod pentru un depozit de backend.
Mergem la abonamentul site-ului nostru Helloworld și mergem la subsecțiunea Git:
Introduceți un link către depozitul nostru Github în câmpul „Depozitar Git la distanță” și schimbați folderul implicit httpdocs la altul (ex. /httpdocs/hw_back):
Copiați cheia publică SSH de la pasul anterior și adăuga este în setările Github.
Faceți clic pe OK pe ecran la pasul 2, după care vom fi redirecționați către pagina de depozit din Plesk. Acum trebuie să configuram depozitul pentru a fi actualizat la comiterea în ramura principală. Pentru a face acest lucru, accesați Setări pentru depozit și salvați valoarea Webhook URL (vom avea nevoie de el mai târziu când configurați Github Actions):
În câmpul Acțiuni de pe ecran din paragraful anterior, introduceți scriptul pentru a lansa implementarea:
cd {REPOSITORY_ABSOLUTE_PATH}
.ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID}
în cazul în care:
{REPOSITORY_ABSOLUTE_PATH} - calea către folderul prod al depozitului backend de pe server; {ENV} - mediu (dev/prod), în cazul nostru prod; {DOCKER_REGISTRY_HOST} - gazda depozitului nostru docker {TG_BOT_TOKEN} — Jeton de bot Telegram; {TG_CHAT_ID} — ID-ul chat-ului/canalului pentru trimiterea notificărilor.
Exemplu de script:
cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
.ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
Adăugați un utilizator din abonamentul nostru la grupul Docker (pentru a putea gestiona containerele):
sudo usermod -aG docker helloworld_admin
Mediul de dezvoltare pentru depozitul de backend și frontend-ul sunt configurate în același mod.
Conducta de implementare în Github Actions
Să trecem la configurarea primei părți a conductei noastre CI/CD în Github Actions.
DEPLOY_HOST — gazdă unde este disponibil panoul de administrare Plesk (exemplu: helloworld.com: 8443 sau 123.4.56.78:8443);
DEPLOY_BACK_PROD_TOKEN - un token pentru implementare în prod-repository de pe server (l-am primit în Deployment in Plesk p. 4);
DEPLOY_BACK_DEV_TOKEN - token pentru implementare în depozitul de dezvoltare de pe server.
Procesul de implementare este simplu și constă din trei pași principali:
construirea și publicarea imaginii în depozitul nostru;
rularea de teste într-un container pe baza unei imagini proaspăt construite;
implementare în mediul dorit în funcție de ramură (dev/master).
Frontend
Fișierul deploy.yml pentru depozitul frontal puțin diferit de cel al lui Beck. Îi lipsește un pas cu rularea testelor și schimbă numele token-urilor pentru implementare. Apropo, secretele pentru depozitul frontal trebuie completate separat.
Configurarea site-ului
Traficul proxy prin Nginx
Ei bine, am ajuns la final. Rămâne doar să configurați proxy traficul de intrare și de ieșire către containerul nostru prin Nginx. Am acoperit deja acest proces la pasul 5 din configurarea Docker Registry. Același lucru ar trebui repetat pentru părțile din spate și din față în mediile de dezvoltare și producție.
Voi oferi capturi de ecran ale setărilor.
Backend
Frontend
Lămurire importantă. Toate adresele URL vor fi trimise proxy către containerul de interfață, cu excepția celor care încep cu /api/ - vor fi proxy de containerul din spate (deci în containerul din spate, toți manipulatorii trebuie să înceapă cu /api/).
Rezultatele
Acum, site-ul nostru ar trebui să fie disponibil la helloworld.ru și dev.helloworld.ru (prod- și, respectiv, dev-medii).
În total, am învățat cum să pregătim o aplicație simplă în Flask și Angular și să configuram o conductă în Github Actions pentru a o implementa pe un server care rulează Plesk.
Voi duplica link-urile către depozite cu codul: backend, în față.