CI/CD in azioni Github per un progetto Flask+Angular

CI/CD in azioni Github per un progetto Flask+Angular
In questo articolo, condividerò la mia esperienza nell'impostazione di CI/CD utilizzando il pannello di controllo di Plesk e le azioni di Github. Oggi impareremo come distribuire un progetto semplice con il nome semplice "Helloworld". È scritto nel framework Flask Python, con lavoratori Celery e un frontend Angular 8.

Collegamenti ai repository: back-end, fine frontale.

Nella prima parte dell'articolo, esamineremo il nostro progetto e le sue parti. Nella seconda, scopriremo come configurare Plesk e installare le estensioni e i componenti necessari (DB, RabbitMQ, Redis, Docker, ecc.).

Nella terza parte, scopriremo finalmente come impostare una pipeline per distribuire il nostro progetto su un server in un ambiente di sviluppo e produzione. E poi lanceremo il sito sul server.

E sì, ho dimenticato di presentarmi. Mi chiamo Oleg Borzov, sono uno sviluppatore fullstack nel team CRM per i gestori di mutui di Domclick.

progetto Panoramica

Per prima cosa, diamo un'occhiata a due repository di progetto - backend e front - e rivediamo il codice.

Backend: Pallone+Sedano

Per la parte posteriore, ho preso un gruppo piuttosto popolare tra gli sviluppatori Python: il framework Flask (per l'API) e Celery (per la coda delle attività). SQLAchemy viene utilizzato come ORM. L'alambicco è usato per le migrazioni. Per la convalida JSON negli handle: Marshmallow.

В repository è presente un file Readme.md con una descrizione dettagliata della struttura e le istruzioni per l'esecuzione del progetto.

API della web part abbastanza semplice, si compone di 6 penne:

  • /ping - per verificare la disponibilità;
  • gestisce la registrazione, l'autorizzazione, la revoca dell'autorizzazione e l'ottenimento di un utente autorizzato;
  • un handle di posta elettronica che inserisce un'attività nella coda di Celery.

Parte di sedano ancora più facile, c'è solo un problema send_mail_task.

Nella cartella /conf ci sono due sottocartelle:

  • docker con due Dockerfile (base.dockerfile per costruire un'immagine di base che cambia raramente e Dockerfile per le assemblee principali);
  • .env_files - con file con variabili di ambiente per diversi ambienti.

Ci sono quattro file docker-compose alla radice del progetto:

  • docker-compose.local.db.yml creare un database locale per lo sviluppo;
  • docker-compose.local.workers.yml per l'allevamento locale del lavoratore, database, Redis e RabbitMQ;
  • docker-compose.test.yml per eseguire test durante la distribuzione;
  • docker-compose.yml per la distribuzione.

E l'ultima cartella che ci interessa... .ci-cd. Contiene script di shell per la distribuzione:

  • deploy.sh — avvio della migrazione e implementazione. Viene eseguito sul server dopo aver creato ed eseguito i test in Github Actions;
  • rollback.sh - rollback dei contenitori alla versione precedente dell'assieme;
  • curl_tg.sh - invio di notifiche di implementazione a Telegram.

Frontend su Angular

Deposito con fronte molto più semplice di quello di Beck. La parte anteriore è composta da tre pagine:

  • Pagina principale con un modulo per l'invio di email e un pulsante di uscita.
  • Pagina di login.
  • Pagina di registrazione.

La pagina principale sembra ascetica:

CI/CD in azioni Github per un progetto Flask+Angular
Ci sono due file alla radice Dockerfile и docker-compose.yml, così come la cartella familiare .ci-cd con un numero leggermente inferiore di script rispetto al repository posteriore (script rimossi per l'esecuzione dei test).

Avvio di un progetto in Plesk

Iniziamo configurando Plesk e creando un abbonamento per il nostro sito.

Installazione delle estensioni

In Plesk, abbiamo bisogno di quattro estensioni:

  • Docker gestire e visualizzare visivamente lo stato dei contenitori nel pannello di amministrazione di Plesk;
  • Git configurare la fase di distribuzione sul server;
  • Let's Encrypt generare (e rinnovare automaticamente) certificati TLS gratuiti;
  • Firewall per configurare il filtraggio del traffico in entrata.

Puoi installarli tramite il pannello di amministrazione di Plesk nella sezione Estensioni:

CI/CD in azioni Github per un progetto Flask+Angular
Non prenderemo in considerazione le impostazioni dettagliate per le estensioni, le impostazioni predefinite andranno bene per i nostri scopi dimostrativi.

Crea un abbonamento e un sito

Successivamente, dobbiamo creare un abbonamento per il nostro sito web helloworld.ru e aggiungere lì il sottodominio dev.helloworld.ru.

  1. Crea un abbonamento per il dominio helloworld.ru e specifica la password di accesso per l'utente di sistema:

    CI/CD in azioni Github per un progetto Flask+Angular
    Seleziona la casella in fondo alla pagina Proteggi il dominio con Let's Encryptse vogliamo impostare HTTPS per il sito:

    CI/CD in azioni Github per un progetto Flask+Angular

  2. Successivamente, in questo abbonamento, crea un sottodominio dev.helloworld.ru (per il quale puoi anche emettere un certificato TLS gratuito):

    CI/CD in azioni Github per un progetto Flask+Angular

Installazione dei componenti del server

Abbiamo un server con OS Debian Allunga 9.12 e pannello di controllo installato Plesk Ossidiana 18.0.27.

Dobbiamo installare e configurare per il nostro progetto:

  • PostgreSQL (nel nostro caso, ci sarà un server con due database per gli ambienti dev e prod).
  • RabbitMQ (stessa, stessa istanza con diversi vhost per gli ambienti).
  • Due istanze Redis (per ambienti di sviluppo e produzione).
  • Registro Docker (per l'archiviazione locale delle immagini Docker create).
  • Interfaccia utente per il registro Docker.

PostgreSQL

Plesk include già il DBMS PostgreSQL, ma non l'ultima versione (al momento della stesura di Plesk Obsidian поддерживал Postgres versioni 8.4–10.8). Vogliamo l'ultima versione per la nostra applicazione (12.3 al momento della stesura di questo documento), quindi la installeremo manualmente.

Istruzioni dettagliate sull'installazione di Postgres su Debian ce n'è in abbondanza su internet (esempio), quindi non li descriverò in dettaglio, mi limiterò a dare i comandi:

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

Considerando che PostgreSQL ha impostazioni di default piuttosto mediocri, è necessario correggere la configurazione. Questo ci aiuterà calcolatrice: devi guidare nei parametri del tuo server e sostituire le impostazioni nel file /etc/postgresql/12/main/postgresql.confa quelli offerti. Va notato qui che tali calcolatori non sono una pallottola magica e la base dovrebbe essere sintonizzata in modo più preciso, in base all'hardware, all'applicazione e alla complessità della query. Ma questo è sufficiente per iniziare.

Oltre alle impostazioni proposte dalla calcolatrice, cambiamo anche in postgresql.confla porta predefinita 5432 a un'altra (nel nostro esempio - 53983).

Dopo aver modificato il file di configurazione, riavviare postgresql-server con il comando:

service postgresql restart

Abbiamo installato e configurato PostgreSQL. Ora creiamo un database, gli utenti per gli ambienti di sviluppo e produzione e concediamo agli utenti i diritti per gestire il database:

$ 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

Passiamo ora all'installazione di RabbitMQ, un message broker per Celery. Viene installato su Debian È molto semplice:

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

Dopo l'installazione, dobbiamo creare vhost, utenti e concedere i diritti necessari:

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

Ora installiamo e configuriamo l'ultimo componente per la nostra applicazione: Redis. Verrà utilizzato come back-end per archiviare i risultati delle attività di Celery.

Aumenteremo due container Docker con Redis per ambienti di sviluppo e produzione utilizzando l'estensione Docker per Plesk.

  1. Andiamo su Plesk, andiamo nella sezione Estensioni, cerchiamo l'estensione Docker e la installiamo (abbiamo bisogno di una versione gratuita):

    CI/CD in azioni Github per un progetto Flask+Angular

  2. Vai all'estensione installata, trova l'immagine attraverso la ricerca redis bitnami e installa l'ultima versione:

    CI/CD in azioni Github per un progetto Flask+Angular

  3. Andiamo nel container scaricato e modifichiamo la configurazione: specifichiamo la porta, la dimensione massima della RAM allocata, la password nelle variabili di ambiente e montiamo il volume:

    CI/CD in azioni Github per un progetto Flask+Angular

  4. Eseguiamo i passaggi 2-3 per il contenitore prod, nelle impostazioni cambiamo solo i parametri: porta, password, dimensione della RAM e percorso della cartella del volume sul server:

    CI/CD in azioni Github per un progetto Flask+Angular

Registro Docker

Oltre ai servizi di base, sarebbe bello mettere sul server il proprio repository di immagini Docker. Fortunatamente, lo spazio sul server ora è abbastanza economico (sicuramente più economico di un abbonamento DockerHub) e il processo di configurazione di un repository privato è molto semplice.

Vogliamo avere:

Per fare ciò:

  1. Creiamo due sottodomini in Plesk nel nostro abbonamento: docker.helloworld.ru e docker-ui.helloworld.ru e configuriamo i certificati Let's Encrypt per loro.
  2. Aggiungi il file alla cartella del sottodominio docker.helloworld.ru docker-compose.yml con contenuti come questo:
    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. Sotto SSH, genereremo il file .htpasswd per l'autorizzazione di base nel repository Docker:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Raccogliere e sollevare i contenitori:
    docker-compose up -d
  5. E dobbiamo reindirizzare Nginx ai nostri container. Questo può essere fatto tramite Plesk.

I seguenti passaggi devono essere eseguiti per i sottodomini docker.helloworld.ru e docker-ui.helloworld.ru:

Nella sezione Strumenti di sviluppo il nostro sito vai a Regole proxy Docker:

CI/CD in azioni Github per un progetto Flask+Angular
E aggiungi una regola per inoltrare il traffico in entrata al nostro contenitore:

CI/CD in azioni Github per un progetto Flask+Angular

  1. Controlliamo di poter accedere al nostro contenitore dalla macchina locale:
    $ 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
  2. Controlliamo anche il funzionamento del sottodominio docker-ui.helloworld.ru:

    CI/CD in azioni Github per un progetto Flask+Angular
    Quando si fa clic su Sfoglia repository, il browser visualizzerà una finestra di autorizzazione in cui sarà necessario inserire il nome utente e la password per il repository. Successivamente, verremo trasferiti a una pagina con un elenco di repository (per ora sarà vuoto per te):

    CI/CD in azioni Github per un progetto Flask+Angular

Apertura delle porte in Plesk Firewall

Dopo aver installato e configurato i componenti, dobbiamo aprire le porte in modo che i componenti siano accessibili dai container Docker e dalla rete esterna.

Vediamo come farlo utilizzando l'estensione Firewall per Plesk che abbiamo installato in precedenza.

  1. Passiamo a Strumenti e Impostazioni > Impostazioni > Firewall:
    CI/CD in azioni Github per un progetto Flask+Angular
  2. Passiamo a Modifica le regole di Plesk Firewall > Aggiungi regola personalizzata e apri le seguenti porte TCP per la sottorete Docker (172.0.0.0 / 8):
    ConiglioMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis: 32785, 32786

    CI/CD in azioni Github per un progetto Flask+Angular

  3. Aggiungeremo anche una regola che aprirà le porte PostgreSQL e i pannelli di gestione RabbitMQ al mondo esterno:

    CI/CD in azioni Github per un progetto Flask+Angular

  4. Applicare le regole utilizzando il pulsante Applica modifiche:

    CI/CD in azioni Github per un progetto Flask+Angular

Configurazione di CI/CD in Github Actions

Passiamo alla parte più interessante: impostare una pipeline di integrazione continua e consegnare il nostro progetto al server.

Questa pipeline sarà composta da due parti:

  • creazione di un'immagine ed esecuzione di test (per il back-end) - sul lato Github;
  • eseguire le migrazioni (per il back-end) e distribuire i contenitori - sul server.

Distribuisci a Plesk

Affrontiamo prima il secondo punto (perché il primo dipende da questo).

Configureremo il processo di distribuzione utilizzando l'estensione Git per Plesk.

Considera un esempio con un ambiente Prod per un repository back-end.

  1. Andiamo all'abbonamento del nostro sito Web Helloworld e andiamo alla sottosezione Git:

    CI/CD in azioni Github per un progetto Flask+Angular

  2. Inserisci un collegamento al nostro repository Github nel campo "Repository Git remoto" e modifica la cartella predefinita httpdocs ad un altro (es. /httpdocs/hw_back):

    CI/CD in azioni Github per un progetto Flask+Angular

  3. Copia la chiave pubblica SSH dal passaggio precedente e aggiungi è nelle impostazioni di Github.
  4. Fare clic su OK sullo schermo nel passaggio 2, dopodiché verremo reindirizzati alla pagina del repository in Plesk. Ora dobbiamo configurare il repository per essere aggiornato sui commit al ramo principale. Per fare questo, vai a Impostazioni del repository e salvare il valore Webhook URL (ne avremo bisogno in seguito durante l'impostazione delle azioni Github):

    CI/CD in azioni Github per un progetto Flask+Angular

  5. Nel campo Azioni nella schermata del paragrafo precedente, inserisci lo script per avviare la distribuzione:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    dove:

    {REPOSITORY_ABSOLUTE_PATH} - percorso della cartella prod del repository back-end sul server;
    {ENV} - ambiente (dev/prod), nel nostro caso prod;
    {DOCKER_REGISTRY_HOST} - l'host del nostro repository docker
    {TG_BOT_TOKEN} — Token bot di Telegram;
    {TG_CHAT_ID} — ID della chat/canale per l'invio delle notifiche.

    Esempio di sceneggiatura:

    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. Aggiungi un utente dal nostro abbonamento al gruppo Docker (in modo che possa gestire i contenitori):
    sudo usermod -aG docker helloworld_admin

L'ambiente di sviluppo per il repository back-end e il front-end sono configurati allo stesso modo.

Pipeline di distribuzione in Github Actions

Passiamo alla configurazione della prima parte della nostra pipeline CI/CD in Github Actions.

BACKEND

La pipeline è descritta in file deploy.yml.

Ma prima di analizzarlo, inseriamo le variabili Secret di cui abbiamo bisogno in Github. Per fare questo, vai a Impostazioni -> Segreti:

  • DOCKER_REGISTRY - l'host del nostro repository Docker (docker.helloworld.ru);
  • DOCKER_LOGIN - accedere al repository Docker;
  • DOCKER_PASSWORD - password per accedervi;
  • DEPLOY_HOST — host in cui è disponibile il pannello di amministrazione di Plesk (esempio: ciaomondo.ru: 8443 o 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN - un token per il deployment nel repository prod sul server (lo abbiamo ottenuto in Deployment in Plesk p. 4);
  • DEPLOY_BACK_DEV_TOKEN - token per la distribuzione nel repository dev sul server.

Il processo di distribuzione è semplice e si compone di tre fasi principali:

  • costruire e pubblicare l'immagine nel nostro repository;
  • esecuzione di test in un contenitore basato su un'immagine appena creata;
  • distribuzione nell'ambiente desiderato a seconda del ramo (dev/master).

Frontend

Il file deploy.yml per il repository anteriore poco diverso da quello di Beck. Manca un passaggio con l'esecuzione dei test e cambia i nomi dei token per la distribuzione. I segreti per il repository anteriore, tra l'altro, devono essere compilati separatamente.

Configurazione del sito

Proxying del traffico tramite Nginx

Bene, siamo arrivati ​​alla fine. Resta solo da configurare l'inoltro del traffico in entrata e in uscita al nostro contenitore tramite Nginx. Abbiamo già coperto questo processo nel passaggio 5 della configurazione del registro Docker. Lo stesso dovrebbe essere ripetuto per le parti anteriore e posteriore negli ambienti di sviluppo e produzione.

Fornirò screenshot delle impostazioni.

BACKEND

CI/CD in azioni Github per un progetto Flask+Angular

Frontend

CI/CD in azioni Github per un progetto Flask+Angular
Chiarimento importante. Tutti gli URL verranno inoltrati al contenitore frontend, ad eccezione di quelli che iniziano con /api/ - saranno inoltrati al back container (so nel contenitore posteriore, tutti i gestori devono iniziare con /api/).

Risultati di

Ora il nostro sito dovrebbe essere disponibile su helloworld.ru e dev.helloworld.ru (prod- e dev-environments, rispettivamente).

In totale, abbiamo imparato come preparare una semplice applicazione in Flask e Angular e configurare una pipeline in Github Actions per implementarla su un server che esegue Plesk.

Duplicherò i collegamenti ai repository con il codice: back-end, fine frontale.

Fonte: habr.com

Acquista hosting affidabile per siti con protezione DDoS, server VPS VDS 🔥 Acquista un hosting web affidabile con protezione DDoS, server VPS e VDS | ProHoster