{"id":85646,"date":"2020-06-18T01:42:15","date_gmt":"2020-06-17T23:42:15","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular"},"modified":"2020-06-18T01:42:15","modified_gmt":"2020-06-17T23:42:15","slug":"ci-cd-v-github-actions-dlya-proekta-na-flask-angular","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","title":{"rendered":"CI\/CD in Github Actions per un progetto su Flask+Angular","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/26d0945a41bbf3c98fa92f15be5b8c6c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIn questo articolo condivider\u00f2 la mia esperienza nella configurazione di CI\/CD utilizzando il pannello di controllo Plesk e Github Actions. Oggi impareremo a distribuire un semplice progetto dal nome poco originale \u00abHelloworld\u00bb. \u00c8 scritto nel framework Python Flask, con worker su Celery e frontend su Angular 8.<\/p>\n<p><b>Link ai repository:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">backend<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">frontend<\/a><\/noindex>.<\/p>\n<p>Nella prima parte dell'articolo daremo un'occhiata al nostro progetto e alle sue parti. Nella seconda, vedremo come configurare Plesk e installare le estensioni e i componenti necessari (DB, RabbitMQ, Redis, Docker, ecc.).<\/p>\n<p>Nella terza parte, finalmente, scopriremo come configurare il pipeline per la distribuzione del nostro progetto sul server nell'ambiente dev e prod. E poi lanceremo il sito sul server.<\/p>\n<p>E s\u00ec, ho dimenticato di presentarmi. Mi chiamo Oleg Borzov, sono uno sviluppatore fullstack nel team CRM per i gestori di mutui presso Domklik. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>Panoramica del progetto<\/h1>\n<p>\nPer iniziare, diamo un'occhiata ai due repository del progetto \u2014 backend e frontend \u2014 e facciamo una rapida revisione del codice.<\/p>\n<h2>Parte backend: Flask+Celery<\/h2>\n<p>\nPer la parte backend ho scelto una combinazione piuttosto popolare tra gli sviluppatori Python: il framework Flask (per API) e Celery (per la queue tasks). Viene utilizzato SQLAlchemy come ORM. Alembic viene utilizzato per le migrazioni. Per la validazione del JSON nelle route viene impiegato Marshmallow.<\/p>\n<p>In <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">repository<\/a><\/noindex> c'\u00e8 un file Readme.md con una descrizione dettagliata della struttura e delle istruzioni per l'avvio del progetto.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_web\">API della parte web<\/a><\/noindex> abbastanza semplice, composta da 6 route:<\/p>\n<ul>\n<li><code>\/ping<\/code> \u2014 per controllare la disponibilit\u00e0;<\/li>\n<li>route per registrazione, autenticazione, de-auth e per ottenere l'utente autenticato;<\/li>\n<li>route per inviare email, che inserisce un task nella coda Celery.<\/li>\n<\/ul>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_celery\">Parte Celery<\/a><\/noindex> ancora pi\u00f9 semplice, c'\u00e8 solo un task <code>send_mail_task<\/code>.<\/p>\n<p>Nella cartella <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/conf\/\">\/conf<\/a><\/noindex> ci sono due sottocartelle: <\/p>\n<ul>\n<li><code>docker<\/code> con due Dockerfile (<code>base.dockerfile<\/code> per la costruzione di un'immagine di base che cambia raramente e <code>Dockerfile<\/code> per le build principali);<\/li>\n<li><code>.env_files<\/code> \u2014 con file delle variabili ambientali per diversi ambienti. <\/li>\n<\/ul>\n<p>\nNella radice del progetto ci sono quattro file docker-compose:<\/p>\n<ul>\n<li><code>docker-compose.local.db.yml<\/code> per avviare un DB locale per lo sviluppo;<\/li>\n<li><code>docker-compose.local.workers.yml<\/code> per avviare localmente il worker, DB, Redis e RabbitMQ;<\/li>\n<li><code>docker-compose.test.yml<\/code> per eseguire test durante il deployment;<\/li>\n<li><code>docker-compose.yml<\/code> per la distribuzione.<\/li>\n<\/ul>\n<p>\nE l'ultima cartella interessante per noi \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/.ci-cd\">.ci-cd<\/a><\/noindex>. In essa ci sono script shell per il deployment:<\/p>\n<ul>\n<li><code>deploy.sh<\/code> \u2014 avvio delle migrazioni e del deployment. Viene eseguito sul server dopo la build e l'esecuzione dei test in Github Actions;<\/li>\n<li><code>rollback.sh<\/code> \u2014 rollback dei container alla versione precedente della build;<\/li>\n<li><code>curl_tg.sh<\/code> \u2014 invio di notifiche sul deployment a Telegram.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Frontend su Angular<\/h2>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">Repository with the front end<\/a><\/noindex> is significantly simpler than the backend. The front consists of three pages:<\/p>\n<ul>\n<li>The main page with an email submission form and a logout button.<\/li>\n<li>Login page.<\/li>\n<li>Registration page.<\/li>\n<\/ul>\n<p>\nThe main page looks minimalistic:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/4db36add2c4277397724b0d71b96ff06.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nThere are two files in the root <code>Dockerfile<\/code> e <code>docker-compose.yml<\/code>, as well as the familiar folder <code>.ci-cd<\/code> with slightly fewer scripts than in the backend repository (scripts for running tests have been removed).<\/p>\n<h1>Setting up a project in Plesk<\/h1>\n<p>\nLet's start by configuring Plesk and creating a subscription for our website.<\/p>\n<h2>Installing extensions<\/h2>\n<p>\nWe will need four extensions in Plesk: <\/p>\n<ul>\n<li><code>Docker<\/code> to manage and visually display the status of containers in the Plesk admin panel;<\/li>\n<li><code>Git<\/code> to set the deployment step on the server;<\/li>\n<li><code>Let's Encrypt<\/code> for generating (and auto-renewing) free TLS certificates;<\/li>\n<li><code>Firewall<\/code> for configuring incoming traffic filtering.<\/li>\n<\/ul>\n<p>\nThey can be installed through the Plesk admin panel in the Extensions section:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/350cf7d7ca3ae1a965a0d3f8a73594ef.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWe will not go into detailed configuration of the extensions; the default settings will suffice for our demo purposes.<\/p>\n<h2>Creating a subscription and website<\/h2>\n<p>\nNext, we need to create a subscription for our website helloworld.ru and add the subdomain dev.helloworld.ru.<\/p>\n<ol>\n<li>We create a subscription for the domain helloworld.ru and specify the username-password for the system user:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3932dc7492aa523b6cbd540ad7a7fe6b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAt the bottom of the page, we check the box <i>Proteggi il dominio con Let's Encrypt<\/i>, if we want to set up HTTPS for the site:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f4d23a34764fdeb411fe2ca9cc95cb45.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Next, in this subscription, we create the subdomain dev.helloworld.ru (for which a free TLS certificate can also be issued):\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d57e6ba71454cb537917400de4275e92.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h1>Installing server components<\/h1>\n<p>\nWe have a server with <i>OS Debian Stretch 9.12<\/i> and the control panel installed <i>Plesk Obsidian 18.0.27<\/i>.<\/p>\n<p>We need to install and configure for our project:<\/p>\n<ul>\n<li>PostgreSQL (in our case, it will be one server with two databases for the dev and prod environments).<\/li>\n<li>RabbitMQ (the same, one instance with different vhosts for the environments).<\/li>\n<li>Two instances of Redis (for the dev and prod environments).<\/li>\n<li>Docker Registry (for local storage of built Docker images).<\/li>\n<li>UI for Docker registry.<\/li>\n<\/ul>\n<p><\/p>\n<h2>PostgreSQL<\/h2>\n<p>\nPlesk already comes with a PostgreSQL DBMS, although not the most recent version (at the time of writing, Plesk Obsidian <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.plesk.com\/release-notes\/obsidian\/software-requirements\/\">supported<\/a><\/noindex> Postgres versions 8.4\u201310.8). We want the latest version for our application (12.3 at the time of writing), so we will install it manually.<\/p>\n<p>There are plenty of detailed instructions for installing Postgres on Debian online (<noindex><a rel=\"nofollow\" href=\"https:\/\/tecadmin.net\/install-postgresql-on-debian-9-stretch\/\">un esempio<\/a><\/noindex>), so I won't describe them in detail, just provide the commands:<\/p>\n<pre><code class=\"bash\">wget -q https:\/\/www.postgresql.org\/media\/keys\/ACCC4CF8.asc -O - | sudo apt-key add -\nsudo sh -c 'echo \"deb http:\/\/apt.postgresql.org\/pub\/repos\/apt\/ stretch-pgdg main\" &gt;&gt; \/etc\/apt\/sources.list.d\/pgdg.list'\n\nsudo apt-get update\nsudo apt-get install postgresql postgresql-contrib\n<\/code><\/pre>\n<p>\nPoich\u00e9 in PostgreSQL le impostazioni predefinite sono piuttosto mediocri, \u00e8 indispensabile modificare la configurazione. A questo ci aiuter\u00e0 <noindex><a rel=\"nofollow\" href=\"http:\/\/pgconfigurator.cybertec.at\/\">un calcolatore<\/a><\/noindex>: bisogna inserire i parametri del proprio server e sostituire le impostazioni nel file <code>\/etc\/postgresql\/12\/main\/postgresql.conf<\/code>con quelle suggerite. \u00c8 importante dire che tali calcolatori non sono una panacea e il database deve essere ottimizzato in modo pi\u00f9 mirato, a seconda dell'hardware, dell'applicazione e della complessit\u00e0 delle query. Ma per iniziare, questo \u00e8 sufficiente.<\/p>\n<p>Oltre alle impostazioni suggerite dal calcolatore, modifichiamo anche <code>, affinch\u00e9 il tuo database di test non voglia effettuare un backup silenziosamente.<\/code>la porta predefinita 5432 in un'altra (nel nostro esempio \u2014 <strong>53983<\/strong>).<\/p>\n<p>Dopo aver modificato il file di configurazione, riavviamo il postgresql-server con il comando:<\/p>\n<pre><code class=\"bash\">service postgresql restart\n<\/code><\/pre>\n<p>\nAbbiamo installato e configurato PostgreSQL. Ora creiamo un database, utenti per gli ambienti dev e prod, e concediamo agli utenti diritti di gestione del database:<\/p>\n<pre><code class=\"bash\">$ su - postgres\npostgres:~$ create database hw_dev_db_name;\nCREATE DATABASE\npostgres:~$ create user hw_dev_db_user with password 'hw_dev_db_password';\nCREATE ROLE\npostgres:~$ grant ALL privileges ON database hw_dev_db_name to hw_dev_db_user;\nGRANT\npostgres:~$ create database hw_prod_db_name;\nCREATE DATABASE\npostgres:~$ create user hw_prod_db_user with password 'hw_prod_db_password';\nCREATE ROLE\npostgres:~$ grant ALL privileges ON database hw_prod_db_name to hw_prod_db_user;\nGRANT\n<\/code><\/pre>\n<p><\/p>\n<h2>RabbitMQ<\/h2>\n<p>\nPassiamo all'installazione di RabbitMQ \u2014 il broker di messaggi per Celery. Si installa su Debian piuttosto facilmente:<\/p>\n<pre><code class=\"bash\">wget https:\/\/packages.erlang-solutions.com\/erlang-solutions_1.0_all.deb\nsudo dpkg -i erlang-solutions_1.0_all.deb\n\nsudo apt-get update\nsudo apt-get install erlang erlang-nox\n\nsudo add-apt-repository 'deb http:\/\/www.rabbitmq.com\/debian\/ testing main'\nwget -O- https:\/\/www.rabbitmq.com\/rabbitmq-release-signing-key.asc | sudo apt-key add -\n\nsudo apt-get update\nsudo apt-get install rabbitmq-server\n<\/code><\/pre>\n<p>\nDopo l'installazione, dobbiamo creare <i>vhosts<\/i>, utenti e concedere i diritti necessari:<\/p>\n<pre><code class=\"bash\">sudo rabbitmqctl add_user hw_dev_amqp_user hw_dev_amqp_password \nsudo rabbitmqctl set_user_tags hw_dev_amqp_user administrator\nsudo rabbitmqctl add_vhost hw_dev_vhost\nsudo rabbitmqctl set_permissions -p hw_dev_vhost hw_dev_amqp_user \".*\" \".*\" \".*\"\n\nsudo rabbitmqctl add_user hw_prod_amqp_user hw_prod_amqp_password \nsudo rabbitmqctl set_user_tags hw_prod_amqp_user administrator\nsudo rabbitmqctl add_vhost hw_prod_vhost\nsudo rabbitmqctl set_permissions -p hw_prod_vhost hw_prod_amqp_user \".*\" \".*\" \".*\"\n<\/code><\/pre>\n<p><\/p>\n<h2>Redis<\/h2>\n<p>\nOra installiamo e configuriamo l'ultimo componente per la nostra applicazione \u2014 Redis. Sar\u00e0 utilizzato come backend per memorizzare i risultati dei task di Celery.<\/p>\n<p>Installeremo due contenitori Docker con Redis per gli ambienti dev e prod utilizzando l'estensione <code>Docker<\/code> per Plesk.<\/p>\n<ol>\n<li>Accediamo a Plesk, andiamo alla sezione Estensioni, cerchiamo l'estensione Docker e la installiamo (abbiamo bisogno della versione gratuita):\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/5638f9b40274e4f7441434279c76a426.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Andiamo all'estensione installata, troviamo tramite ricerca l'immagine <code>redis bitnami<\/code> e installiamo l'ultima versione:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/578bbbed6a66a60a4f7410f7d61ea542.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Entriamo nel container scaricato e modifichiamo la configurazione: indichiamo la porta, la dimensione massima della RAM, la password nelle variabili d'ambiente e montiamo il volume:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/8bc804b794735412f5e510b3049c5667.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Eseguiamo i passaggi 2-3 per il container prod, nelle impostazioni cambiamo solo i parametri: porta, password, dimensione della RAM e percorso della cartella volume sul server:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3af50181c8b3e1ace23a8de11826cb51.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h2>Docker Registry<\/h2>\n<p>\nOltre ai servizi di base, sarebbe utile installare sul server un proprio repository di immagini Docker. Dato che lo spazio sui server \u00e8 attualmente piuttosto economico (sicuramente pi\u00f9 economico di un abbonamento a DockerHub), e il processo di installazione di un repository privato \u00e8 molto semplice. <\/p>\n<p>Vogliamo installare:<\/p>\n<ul>\n<li>un repository Docker protetto da password, accessibile tramite sottodominio <noindex><a rel=\"nofollow\" href=\"https:\/\/docker.helloworld.ru\">https:\/\/docker.helloworld.ru<\/a><\/noindex>;<\/li>\n<li>Interfaccia UI per visualizzare le immagini nel repository, accessibile all'indirizzo <noindex><a rel=\"nofollow\" href=\"https:\/\/docker-ui.helloworld.ru\">https:\/\/docker-ui.helloworld.ru<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\nPer questo:<\/p>\n<ol>\n<li>Creeremo in Plesk due sottodomini nel nostro abbonamento: docker.helloworld.ru e docker-ui.helloworld.ru, e configureremo per loro i certificati Let\u2019s Encrypt.<\/li>\n<li>Nella cartella del sottodominio docker.helloworld.ru aggiungiamo il file <code>docker-compose.yml<\/code> con il seguente contenuto:\n<pre><code class=\"plaintext\">version: \"3\"\n\nservices:\n  docker-registry:\n    image: \"registry:2\"\n    restart: always\n    ports:\n      - \"53985:5000\"\n    environment:\n      REGISTRY_AUTH: htpasswd\n      REGISTRY_AUTH_HTPASSWD_REALM: basic-realm\n      REGISTRY_AUTH_HTPASSWD_PATH: \/auth\/.htpasswd\n      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: \/data\n    volumes:\n      - .\/.docker-registry.htpasswd:\/auth\/.htpasswd\n      - .\/data:\/data\n\n  docker-registry-ui:\n    image: konradkleine\/docker-registry-frontend:v2\n    restart: always\n    ports:\n      - \"53986:80\"\n    environment:\n      VIRTUAL_HOST: '*, https:\/\/*'\n      ENV_DOCKER_REGISTRY_HOST: 'docker-registry'\n      ENV_DOCKER_REGISTRY_PORT: 5000\n    links:\n      - 'docker-registry'\n<\/code><\/pre>\n<p>\n<\/li>\n<li>Tramite SSH generiamo il file .htpasswd per l'autenticazione Base nel repository Docker:\n<pre><code class=\"plaintext\">htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password<\/code><\/pre>\n<\/li>\n<li>Costruiamo e avviamo i container:\n<pre><code class=\"plaintext\">docker-compose up -d<\/code><\/pre>\n<\/li>\n<li>E dobbiamo indirizzare Nginx ai nostri container. Possiamo farlo tramite Plesk. <\/li>\n<\/ol>\n<p>\nLe seguenti operazioni devono essere eseguite per i sottodomini docker.helloworld.ru e docker-ui.helloworld.ru:<\/p>\n<p>Nella sezione <i>Strumenti per sviluppatori<\/i> del nostro sito andiamo su <i>Regole Proxy Docker<\/i>:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d9c05901d95d61ce5db27a1a7cfddf49.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nE aggiungiamo una regola per il proxy del traffico in entrata nel nostro container:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/faa85cf6da648ef55b7c87c44040efb1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<ol>\n<li>Verifichiamo di poter accedere al nostro container dalla macchina locale:\n<pre><code class=\"plaintext\">$ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password\nATTENZIONE! L'uso di --password tramite CLI \u00e8 insicuro. Utilizzare --password-stdin.\nLogin riuscito<\/code><\/pre>\n<\/li>\n<li>Verifichiamo anche il funzionamento del sottodominio docker-ui.helloworld.ru:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/fdd6e1396c27c02a88bcbd7efb12f247.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nQuando clicchi su Browse repositories, il browser visualizzer\u00e0 una finestra di autorizzazione in cui dovrai inserire il nome utente e la password per il repository. Successivamente, verrai reindirizzato a una pagina con l'elenco dei repository (che al momento sar\u00e0 vuota):<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f2d75edb530e9d746095ae02d7793c1f.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h2>Aprire le porte nel Firewall di Plesk<\/h2>\n<p>\nDopo l'installazione e la configurazione dei componenti, dobbiamo aprire le porte affinch\u00e9 i componenti siano accessibili dai container Docker e dalla rete esterna.<\/p>\n<p>Vediamo come fare, prendendo come esempio l'estensione Firewall precedentemente installata in Plesk.<\/p>\n<ol>\n<li>Passiamo a <i>Strumenti &amp; Impostazioni &gt; Impostazioni &gt; Firewall<\/i>:<br \/>\n<img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d54b4941944fe191574472a475cbaebe.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Passiamo a <i>Modifica delle Regole del Firewall di Plesk &gt; Aggiungi Regola Personalizzata<\/i> e apriamo le seguenti porte TCP per la subnet Docker (<strong>172.0.0.0\/8)<\/strong>:<br \/>\nRabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614<br \/>\nRedis: 32785, 32786<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3359845f9bd6dc303274da737d4b27a2.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Aggiungiamo anche una regola che apra al mondo esterno le porte per PostgreSQL e il pannello di gestione di RabbitMQ:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f812cfc7127da469507538ea48b2c80d.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Applichiamo le regole premendo il pulsante Applica Modifiche:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/e85444ae717aaefa796664003fc86578.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h1>Configurazione CI\/CD in Github Actions<\/h1>\n<p>\nIniziamo con la parte pi\u00f9 interessante: configurare il pipeline di integrazione continua e delivery del nostro progetto sul server.<\/p>\n<p>Questo pipeline sar\u00e0 composto da due parti: <\/p>\n<ul>\n<li>costruzione dell'immagine e esecuzione dei test (per il backend) \u2014 lato Github;<\/li>\n<li>esecuzione delle migrazioni (per il backend) e deploy dei container \u2014 sul server.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Deploy in Plesk<\/h2>\n<p>\nIniziamo con il secondo punto (dato che il primo ne dipende).<\/p>\n<p>Configureremo il processo di deploy utilizzando l'estensione Git per Plesk.<\/p>\n<p>Consideriamo un esempio con l'ambiente Prod per il repository Backend.<\/p>\n<ol>\n<li>Accediamo all'abbonamento del nostro sito Helloworld e andiamo alla sezione Git:\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/b55b371560ea87a2954b6553a7cefc49.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Incolliamo nel campo \"Remote Git repository\" il link al nostro repository Github e cambiamo la cartella predefinita <code>httpdocs<\/code> in un'altra (ad esempio, <code>\/httpdocs\/hw_back<\/code>):\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/db9ba9adb6e2e1bed5da7ae8e88c76e1.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Copia la chiave pubblica SSH dal passaggio precedente e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/settings\/ssh\/new\">aggiungiamo<\/a><\/noindex> inseriscila nelle impostazioni di Github.<\/li>\n<li>Clicca su OK nella schermata al punto 2, dopo di che verrai reindirizzato alla pagina del repository in Plesk. Ora dobbiamo configurare l'aggiornamento del repository con i commit nel branch master. Per fare ci\u00f2, passiamo a <i>Impostazioni del Repository<\/i> e salviamo il valore <code>Webhook URL<\/code> (ci servir\u00e0 pi\u00f9 avanti nella configurazione di Github Actions):\n<p><img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/14d48a357f821d734d40dc434ab3682a.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Nel campo Actions nella schermata del passaggio precedente, inseriamo lo script per avviare il deploy:\n<pre><code class=\"plaintext\">cd {REPOSITORY_ABSOLUTE_PATH}\n.ci-cd\/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} <\/code><\/pre>\n<p>\ndove: <\/p>\n<p><code>{REPOSITORY_ABSOLUTE_PATH}<\/code> \u2014 il percorso della cartella del repository backend prod sul server;<br \/>\n<code>{ENV}<\/code> \u2014 ambiente (dev\/prod), nel nostro caso <code>prod<\/code>;<br \/>\n<code>{DOCKER_REGISTRY_HOST}<\/code> \u2014 host del nostro repository docker<br \/>\n<code>{TG_BOT_TOKEN}<\/code> \u2014 token del bot di Telegram;<br \/>\n<code>{TG_CHAT_ID}<\/code> \u2014 ID della chat\/canale per inviare notifiche.<\/p>\n<p>Esempio di script:<\/p>\n<pre><code class=\"plaintext\">cd \/var\/www\/vhosts\/helloworld.ru\/httpdocs\/hw_back\/\n.ci-cd\/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890<\/code><\/pre>\n<\/li>\n<li>Aggiungiamo un utente dal nostro abbonamento al gruppo Docker (in modo che possa gestire i container):\n<pre><code class=\"plaintext\">sudo usermod -aG docker helloworld_admin<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>\nL'ambiente Dev per il repository backend e frontend \u00e8 configurato in modo simile.<\/p>\n<h2>Pipeline di deployment in Github Actions<\/h2>\n<p>\nProcediamo alla configurazione della prima parte del nostro CI\/CD pipeline in Github Actions.<\/p>\n<h3>Backend<\/h3>\n<p>\nIl pipeline \u00e8 descritto nel <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/blob\/master\/.github\/workflows\/deploy.yml\">file deploy.yml<\/a><\/noindex>. <\/p>\n<p>Ma prima di esaminarlo, dobbiamo riempire le variabili Secret di cui abbiamo bisogno in Github. A tal fine, andiamo su <i>Impostazioni -&gt; Segreti<\/i>:<\/p>\n<ul>\n<li><code>DOCKER_REGISTRY<\/code> \u2014 l'host del nostro repository Docker (docker.helloworld.ru);<\/li>\n<li><code>DOCKER_LOGIN<\/code> \u2014 login per il repository Docker;<\/li>\n<li><code>DOCKER_PASSWORD<\/code> \u2014 password per esso;<\/li>\n<li><code>DEPLOY_HOST<\/code> \u2014 l'host in cui \u00e8 disponibile il pannello di amministrazione Plesk (esempio: <noindex><a rel=\"nofollow\" href=\"https:\/\/helloworld.ru\">helloworld.ru<\/a><\/noindex>:8443 o <noindex><a rel=\"nofollow\" href=\"http:\/\/123.4.56.78\">123.4.56.78<\/a><\/noindex>:8443);<\/li>\n<li><code>DEPLOY_BACK_PROD_TOKEN<\/code> \u2014 token per il deployment nel repository di produzione sul server (lo abbiamo ottenuto in Deployment in Plesk p. 4);<\/li>\n<li><code>DEPLOY_BACK_DEV_TOKEN<\/code> \u2014 token per il deployment nel repository di sviluppo sul server.<\/li>\n<\/ul>\n<p>\nIl processo di deployment \u00e8 semplice e consiste in tre passaggi principali: <\/p>\n<ul>\n<li>build e pubblicazione dell'immagine nel nostro repository;<\/li>\n<li>esecuzione dei test nel container basato sull'immagine appena costruita;<\/li>\n<li>deployment nell'ambiente necessario a seconda del ramo (dev\/master).<\/li>\n<\/ul>\n<p><\/p>\n<h3>Frontend<\/h3>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\/blob\/master\/.github\/workflows\/deploy.yml\">Il file deploy.yml per il repository frontend<\/a><\/noindex> differisce poco da quello backend. Manca il passaggio di esecuzione dei test e i nomi dei token per il deployment vengono modificati. I segreti per il repository frontend, tra l'altro, devono essere riempiti separatamente.<\/p>\n<h1>Configurazione del sito<\/h1>\n<p><\/p>\n<h2>Proxy del traffico tramite Nginx<\/h2>\n<p>\nBene, siamo arrivati alla fine. Resta solo da configurare il proxy del traffico in entrata e in uscita nel nostro container tramite Nginx. Questo processo \u00e8 stato gi\u00e0 esaminato nel punto 5 della configurazione del Docker Registry. Lo stesso deve essere ripetuto per le parti backend e frontend negli ambienti dev e prod.<\/p>\n<p>Mostrer\u00f2 degli screenshot delle impostazioni.<\/p>\n<h3>Backend<\/h3>\n<p>\n<img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f3c38dc1c25b648db000c72ef2d30b2a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h3>Frontend<\/h3>\n<p>\n<img decoding=\"async\" alt=\"CI\/CD in Github Actions per un progetto su Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/35d4d8ef3489608db1e173b7f214ca03.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<strong>Importante precisazione<\/strong>. Nel container frontend verranno proxy tutti gli URL, tranne quelli che iniziano con <code>\/api\/<\/code> \u2014 essi saranno router nel container backend (perci\u00f2 <strong>nel container backend tutti i gestori devono iniziare con <\/strong><strong><code>\/api\/<\/code><\/strong>).<\/p>\n<h2>Conclusioni<\/h2>\n<p>\nOra il nostro sito dovrebbe essere accessibile agli indirizzi helloworld.ru e dev.helloworld.ru (rispettivamente per gli ambienti prod e dev).<\/p>\n<p>In conclusione, abbiamo appreso come preparare una semplice applicazione su Flask e Angular e configurare un pipeline in Github Actions per il suo deployment su un server gestito da Plesk.<\/p>\n<p>Ripeter\u00f2 i link ai repository con il codice: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">backend<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">frontend<\/a><\/noindex>.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/506802\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Plesk \u0438 Github Actions. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0435\u043c \u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00abHelloworld\u00bb. \u041e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Python-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435 Flask, \u0441 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438 \u043d\u0430 Celery \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u043d\u0430 Angular 8. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438: \u0431\u044d\u043a\u0435\u043d\u0434, \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434. \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":85647,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-85646","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47CI\/CD \u0432 Github Actions \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Flask+Angular | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-17T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-17T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47CI\/CD in Github Actions per un progetto su Flask+Angular | ProHoster","description":"In questo articolo condivider\u00f2 la mia esperienza.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47CI\/CD \u0432 Github Actions \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Flask+Angular | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-06-17T23:42:15+00:00","article:modified_time":"2020-06-17T23:42:15+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"85646","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:12:50","updated":"2022-09-29 06:56:26","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/85646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=85646"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/85646\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/85647"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=85646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=85646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=85646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}