
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: , .
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.
В è presente un file Readme.md con una descrizione dettagliata della struttura e le istruzioni per l'esecuzione del progetto.
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.
ancora più facile, c'è solo un problema send_mail_task.
Nella cartella ci sono due sottocartelle:
dockercon due Dockerfile (base.dockerfileper costruire un'immagine di base che cambia raramente eDockerfileper 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.ymlcreare un database locale per lo sviluppo;docker-compose.local.workers.ymlper l'allevamento locale del lavoratore, database, Redis e RabbitMQ;docker-compose.test.ymlper eseguire test durante la distribuzione;docker-compose.ymlper la distribuzione.
E l'ultima cartella che ci interessa... . 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
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 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:
Dockergestire e visualizzare visivamente lo stato dei contenitori nel pannello di amministrazione di Plesk;Gitconfigurare la fase di distribuzione sul server;Let's Encryptgenerare (e rinnovare automaticamente) certificati TLS gratuiti;Firewallper configurare il filtraggio del traffico in entrata.
Puoi installarli tramite il pannello di amministrazione di Plesk nella sezione Estensioni:

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.
- Crea un abbonamento per il dominio helloworld.ru e specifica la password di accesso per l'utente di sistema:

Seleziona la casella in fondo alla pagina Proteggi il dominio con Let's Encryptse vogliamo impostare HTTPS per il sito:
- Successivamente, in questo abbonamento, crea un sottodominio dev.helloworld.ru (per il quale puoi anche emettere un certificato TLS gratuito):

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 (), 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à : 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.
- Andiamo su Plesk, andiamo nella sezione Estensioni, cerchiamo l'estensione Docker e la installiamo (abbiamo bisogno di una versione gratuita):

- Vai all'estensione installata, trova l'immagine attraverso la ricerca
redis bitnamie installa l'ultima versione:
- 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:

- 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:

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:
- repository Docker protetto da password accessibile su un sottodominio ;
- Interfaccia utente per la visualizzazione delle immagini nel repository, disponibile all'indirizzo .
Per fare ciò:
- 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.
- Aggiungi il file alla cartella del sottodominio docker.helloworld.ru
docker-compose.ymlcon 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' - Sotto SSH, genereremo il file .htpasswd per l'autorizzazione di base nel repository Docker:
htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password - Raccogliere e sollevare i contenitori:
docker-compose up -d - 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:

E aggiungi una regola per inoltrare il traffico in entrata al nostro contenitore:

- 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 - Controlliamo anche il funzionamento del sottodominio docker-ui.helloworld.ru:

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):
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.
- Passiamo a Strumenti e Impostazioni > Impostazioni > Firewall:

- 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
- Aggiungeremo anche una regola che aprirà le porte PostgreSQL e i pannelli di gestione RabbitMQ al mondo esterno:

- Applicare le regole utilizzando il pulsante Applica modifiche:

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.
- Andiamo all'abbonamento del nostro sito Web Helloworld e andiamo alla sottosezione Git:

- Inserisci un collegamento al nostro repository Github nel campo "Repository Git remoto" e modifica la cartella predefinita
httpdocsad un altro (es./httpdocs/hw_back):
- Copia la chiave pubblica SSH dal passaggio precedente e è nelle impostazioni di Github.
- 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):
- 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 casoprod;
{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 - 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 .
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: : 8443 o :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
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

Frontend

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: , .
Fonte: habr.com
