CI/CD dans Github Actions pour un projet Flask+Angular.

CI/CD dans Github Actions pour un projet Flask+Angular.
Dans cet article, je vais partager mon expérience de configuration CI/CD à l'aide du panneau de contrÎle Plesk et de Github Actions. Aujourd'hui, nous allons apprendre à déployer un projet simple intitulé « Helloworld ». Il est écrit sur le framework Python Flask, avec des workers sur Celery et un frontend sur Angular 8.

Liens vers les dépÎts : backend, frontend.

Dans la premiÚre partie de l'article, nous examinerons notre projet et ses composants. Dans la seconde, nous verrons comment configurer Plesk et installer les extensions et composants nécessaires (BD, RabbitMQ, Redis, Docker, etc.).

Dans la troisiÚme partie, nous verrons enfin comment configurer le pipeline pour déployer notre projet sur le serveur dans les environnements dev et prod. Puis nous lancerons le site sur le serveur.

Ah oui, j'ai oubliĂ© de me prĂ©senter. Je m'appelle Oleg Borzov, je suis dĂ©veloppeur fullstack dans l'Ă©quipe CRM pour les gestionnaires de prĂȘts hypothĂ©caires chez Domclick.

Aperçu du projet

Pour commencer, examinons les deux dĂ©pĂŽts du projet — backend et frontend — et parcourons le code.

Partie backend : Flask+Celery

Pour la partie backend, j'ai choisi une combinaison assez populaire parmi les dĂ©veloppeurs Python : le framework Flask (pour l'API) et Celery (pour la file d'attente des tĂąches). SQLAlchemy est utilisĂ© comme ORM. Alembic est utilisĂ© pour les migrations. Pour la validation JSON dans les handlers — Marshmallow.

Dans dépÎts il y a un fichier Readme.md avec une description détaillée de la structure et des instructions pour exécuter le projet.

API de la partie web assez simple, composée de 6 handlers :

  • /ping — pour vĂ©rifier la disponibilitĂ© ;
  • handlers pour l'inscription, l'authentification, la dĂ©sauthentification et l'obtention de l'utilisateur authentifiĂ© ;
  • handler pour l'envoi d'email, qui place une tĂąche dans la file d'attente Celery.

Partie Celery encore plus simple, il n'y a qu'une seule tĂąche send_mail_task.

Dans le dossier /conf il y a deux sous-dossiers :

  • docker avec deux fichiers Docker (base.dockerfile pour construire une image de base peu modifiĂ©e et Dockerfile pour les constructions principales) ;
  • .env_files — avec des fichiers de variables d'environnement pour diffĂ©rents environnements.

À la racine du projet, il y a quatre fichiers docker-compose :

  • docker-compose.local.db.yml pour lever une BD locale pour le dĂ©veloppement ;
  • docker-compose.local.workers.yml pour lever localement un worker, BD, Redis et RabbitMQ ;
  • docker-compose.test.yml pour exĂ©cuter des tests lors du dĂ©ploiement ;
  • docker-compose.yml pour le dĂ©ploiement.

Et le dernier dossier intĂ©ressant pour nous — .ci-cd. Il contient des scripts shell pour le dĂ©ploiement :

  • deploy.sh — lancement des migrations et du dĂ©ploiement. Il est exĂ©cutĂ© sur le serveur aprĂšs la construction et l'exĂ©cution des tests dans Github Actions ;
  • rollback.sh — restauration des conteneurs Ă  la version prĂ©cĂ©dente de la construction ;
  • curl_tg.sh — envoi de notifications de dĂ©ploiement sur Telegram.

Frontend sur Angular

DépÎt avec le frontend beaucoup plus simple que le backend. Le frontend se compose de trois pages :

  • Page d'accueil avec un formulaire d'envoi d'email et un bouton de dĂ©connexion.
  • Page de connexion.
  • Page d'inscription.

La page d'accueil a un design minimaliste :

CI/CD dans Github Actions pour un projet Flask+Angular.
À la racine se trouvent deux fichiers Dockerfile et docker-compose.yml, ainsi qu'un dossier familier .ci-cd avec un nombre de scripts lĂ©gĂšrement infĂ©rieur Ă  celui du dĂ©pĂŽt backend (les scripts pour exĂ©cuter des tests ont Ă©tĂ© supprimĂ©s).

Créons un projet dans Plesk

Commençons par la configuration de Plesk et la création d'un abonnement pour notre site.

Installation des extensions

Dans Plesk, nous aurons besoin de quatre extensions :

  • Docker pour gĂ©rer et afficher visuellement l'Ă©tat des conteneurs dans l'interface d'administration de Plesk ;
  • Git pour configurer l'Ă©tape de dĂ©ploiement sur le serveur ;
  • Let's Encrypt pour gĂ©nĂ©rer (et renouveler automatiquement) des certificats TLS gratuits ;
  • Pare-feu pour configurer le filtrage du trafic entrant.

Nous pouvons les installer via l'interface d'administration de Plesk dans la section Extensions :

CI/CD dans Github Actions pour un projet Flask+Angular.
Nous ne traiterons pas la configuration détaillée des extensions, les paramÚtres par défaut conviendront pour nos objectifs de démonstration.

Création d'un abonnement et d'un site

Ensuite, nous devons créer un abonnement pour notre site helloworld.ru et ajouter le sous-domaine dev.helloworld.ru.

  1. Créons un abonnement pour le domaine helloworld.ru et indiquons le nom d'utilisateur et le mot de passe pour l'utilisateur systÚme :

    CI/CD dans Github Actions pour un projet Flask+Angular.
    Au bas de la page, cocher la case Sécuriser le domaine avec Let's Encrypt, si nous voulons configurer HTTPS pour le site :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  2. Puis dans cet abonnement, crĂ©ons le sous-domaine dev.helloworld.ru (pour lequel un certificat TLS gratuit peut Ă©galement ĂȘtre Ă©mis) :

    CI/CD dans Github Actions pour un projet Flask+Angular.

Installation des composants serveur

Nous avons à disposition un serveur avec OS Debian Stretch 9.12 et le panneau de contrÎle installé Plesk Obsidian 18.0.27.

Nous devons installer et configurer pour notre projet :

  • PostgreSQL (dans notre cas, il y aura un serveur avec deux bases de donnĂ©es pour les environnements dev et prod).
  • RabbitMQ (mĂȘme chose, une instance avec diffĂ©rents vhosts pour les environnements).
  • Deux instances Redis (pour les environnements dev et prod).
  • Docker Registry (pour le stockage local des images Docker gĂ©nĂ©rĂ©es).
  • Interface utilisateur pour Docker registry.

PostgreSQL

Avec Plesk, il y a déjà une base de données PostgreSQL incluse, mais pas à jour (au moment de la rédaction de cet article, Plesk Obsidian supportait les versions de Postgres 8.4 à 10.8). Nous souhaitons pour notre application la derniÚre version (12.3 au moment de la rédaction de cet article), donc nous allons l'installer manuellement.

Il existe de nombreuses instructions détaillées pour installer Postgres sur Debian en ligne (exemple), c'est pourquoi je ne vais pas les décrire en détail, je vais simplement donner les commandes :

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

Étant donnĂ© que PostgreSQL a des paramĂštres par dĂ©faut plutĂŽt mĂ©diocres, il est essentiel de corriger la configuration. Pour cela, nous allons utiliser calculateur: il faut entrer les paramĂštres de votre serveur et remplacer les configurations dans le fichier /etc/postgresql/12/main/postgresql.confpar celles proposĂ©es. Il convient de prĂ©ciser que ces calculateurs ne sont pas une solution miracle, et la base doit ĂȘtre ajustĂ©e de maniĂšre plus prĂ©cise en fonction de votre matĂ©riel, de vos applications et de la complexitĂ© des requĂȘtes. Mais pour commencer, cela suffit.

En plus des paramĂštres suggĂ©rĂ©s par le calculateur, nous changeons dans postgresql.confle port par dĂ©faut 5432 Ă  un autre (dans notre exemple — 53983).

AprÚs avoir modifié le fichier de configuration, redémarrons le serveur postgresql avec la commande :

service postgresql restart

Nous avons installé et configuré PostgreSQL. Maintenant, créons une base de données, des utilisateurs pour les environnements dev et prod, et attribuons aux utilisateurs des droits de gestion de la base de données :

$ 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

Passons à l'installation de RabbitMQ — le courtier de messages pour Celery. Il s'installe assez facilement sur Debian :

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

AprÚs l'installation, nous devons créer vhosts, des utilisateurs et leur attribuer les droits nécessaires :

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

Nous allons maintenant installer et configurer le dernier composant pour notre application — Redis. Il sera utilisĂ© comme backend pour stocker les rĂ©sultats des tĂąches Celery.

Nous allons déployer deux conteneurs Docker avec Redis pour les environnements dev et prod à l'aide de l'extension Docker pour Plesk.

  1. Accédez à Plesk, allez dans la section Extensions, recherchez l'extension Docker et installez-la (nous avons besoin de la version gratuite) :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  2. Allez dans l'extension installée, recherchez l'image redis bitnami et installez la derniÚre version :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  3. Accédez au conteneur téléchargé et modifiez la configuration : indiquez le port, la taille maximale de la RAM allouée, le mot de passe dans les variables d'environnement, et montez le volume :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  4. Répétez les étapes 2-3 pour le conteneur prod, en modifiant seulement les paramÚtres : port, mot de passe, taille de la RAM et chemin du dossier volume sur le serveur :

    CI/CD dans Github Actions pour un projet Flask+Angular.

Docker Registry

En plus des services de base, il serait utile d'installer un dépÎt Docker privé sur le serveur. Heureusement, l'espace sur les serveurs est maintenant suffisamment bon marché (certainement moins cher qu'un abonnement à DockerHub), et le processus d'installation d'un dépÎt privé est trÚs simple.

Nous souhaitons avoir installé :

Pour cela :

  1. CrĂ©ons dans Plesk deux sous-domaines dans notre abonnement : docker.helloworld.ru et docker-ui.helloworld.ru, et configurons des certificats Let’s Encrypt pour eux.
  2. Dans le dossier du sous-domaine docker.helloworld.ru, ajoutons le fichier docker-compose.yml avec ce contenu :
    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. Avec SSH, générez le fichier .htpasswd pour la Basic-authentification dans le dépÎt Docker :
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Construisons et lançons les conteneurs :
    docker-compose up -d
  5. Et il faut rediriger Nginx vers nos conteneurs. Cela peut se faire via Plesk.

Les actions suivantes doivent ĂȘtre effectuĂ©es pour les sous-domaines docker.helloworld.ru et docker-ui.helloworld.ru :

Dans la section Dev Tools de notre site, accédez à RÚgles Proxy Docker:

CI/CD dans Github Actions pour un projet Flask+Angular.
Et ajoutez une rĂšgle pour le proxy du trafic entrant vers notre conteneur :

CI/CD dans Github Actions pour un projet Flask+Angular.

  1. Vérifions que nous pouvons nous authentifier dans notre conteneur depuis la machine locale :
    $ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password
    AVERTISSEMENT ! L'utilisation de --password via la CLI est peu sécurisée. Utilisez --password-stdin.
    Connexion réussie
  2. Vérifions également le fonctionnement du sous-domaine docker-ui.helloworld.ru :

    CI/CD dans Github Actions pour un projet Flask+Angular.
    En cliquant sur Parcourir les dĂ©pĂŽts, le navigateur affichera une fenĂȘtre d'authentification oĂč vous devrez entrer votre nom d'utilisateur et votre mot de passe pour le dĂ©pĂŽt. Ensuite, nous serons redirigĂ©s vers une page contenant la liste des dĂ©pĂŽts (qui sera encore vide au dĂ©but) :

    CI/CD dans Github Actions pour un projet Flask+Angular.

Ouvrir les ports dans le pare-feu Plesk

AprÚs l'installation et la configuration des composants, nous devons ouvrir des ports pour que les composants soient accessibles à partir des conteneurs Docker et du réseau externe.

Voyons comment procéder, en prenant en exemple l'extension Firewall que nous avons installée précédemment pour Plesk.

  1. Passons Ă  Outils & ParamĂštres > ParamĂštres > Pare-feu:
    CI/CD dans Github Actions pour un projet Flask+Angular.
  2. Passons à Modifier les rÚgles du pare-feu Plesk > Ajouter une rÚgle personnalisée et ouvrir les ports TCP suivants pour le sous-réseau Docker (172.0.0.0/8):
    RabbitMQ : 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis : 32785, 32786

    CI/CD dans Github Actions pour un projet Flask+Angular.

  3. Ajoutons également une rÚgle pour ouvrir au monde extérieur les ports de PostgreSQL et du panneau de gestion de RabbitMQ :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  4. Appliquez les rĂšgles Ă  l'aide du bouton Appliquer les modifications :

    CI/CD dans Github Actions pour un projet Flask+Angular.

Configuration CI/CD dans Github Actions

Passons Ă  la partie la plus intĂ©ressante — la configuration du pipeline d'intĂ©gration et de dĂ©ploiement continus de notre projet sur le serveur.

Ce pipeline sera composé de deux parties :

  • construction de l'image et exĂ©cution des tests (pour le backend) — du cĂŽtĂ© de Github ;
  • exĂ©cution des migrations (pour le backend) et dĂ©ploiement des conteneurs — sur le serveur.

Déploiement dans Plesk

Commençons par le second point (car le premier dépend de lui).

Nous allons configurer le processus de déploiement à l'aide de l'extension Git pour Plesk.

Prenons un exemple avec l'environnement Prod pour le dépÎt Backend.

  1. Accédez à l'abonnement de notre site Helloworld et allez dans la section Git :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  2. Collez dans le champ « DépÎt Git distant » le lien vers notre dépÎt Github et changez le dossier par défaut httpdocs en un autre (par exemple, /httpdocs/hw_back):

    CI/CD dans Github Actions pour un projet Flask+Angular.

  3. Copiez la clé publique SSH de l'étape précédente et ajoutons ajoutez-la dans les paramÚtres de Github.
  4. Cliquez sur OK à l'écran au point 2, puis vous serez redirigé vers la page du dépÎt dans Plesk. Maintenant, nous devons configurer la mise à jour du dépÎt lors des commits sur la branche master. Pour ce faire, allons dans ParamÚtres du dépÎt et sauvegardez la valeur Webhook URL (cela nous sera utile plus tard lors de la configuration de Github Actions) :

    CI/CD dans Github Actions pour un projet Flask+Angular.

  5. Dans le champ Actions à l'écran précédent, saisissez le script pour lancer le déploiement :
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    oĂč :

    {REPOSITORY_ABSOLUTE_PATH} — chemin vers le dossier prod du dĂ©pĂŽt backend sur le serveur ;
    {ENV} — environnement (dev/prod), dans notre cas prod;
    {DOCKER_REGISTRY_HOST} — hĂŽte de notre dĂ©pĂŽt docker
    {TG_BOT_TOKEN} — token du bot Telegram ;
    {TG_CHAT_ID} — ID du chat/canal pour l'envoi de notifications.

    Exemple 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
  6. Nous ajoutons un utilisateur de notre abonnement au groupe Docker (pour qu'il puisse gérer les conteneurs) :
    sudo usermod -aG docker helloworld_admin

L'environnement de dĂ©veloppement pour le dĂ©pĂŽt backend et frontend s'configure de la mĂȘme maniĂšre.

Pipeline de déploiement dans Github Actions

Passons Ă  la configuration de la premiĂšre partie de notre pipeline CI/CD dans Github Actions.

Backend

Le pipeline est décrit dans le fichier deploy.yml.

Mais avant de l'examiner, remplissons dans Github les variables secrÚtes nécessaires. Pour cela, nous allons dans ParamÚtres -> Secrets:

  • DOCKER_REGISTRY — l'hĂŽte de notre dĂ©pĂŽt Docker (docker.helloworld.ru);
  • DOCKER_LOGIN — identifiant pour le dĂ©pĂŽt Docker;
  • DOCKER_PASSWORD — mot de passe pour cela;
  • DEPLOY_HOST — l'hĂŽte oĂč l'interface Plesk est accessible (exemple : helloworld.ru:8443 ou 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN — jeton pour dĂ©ployer dans le dĂ©pĂŽt de production sur le serveur (nous l'avons obtenu dans le dĂ©ploiement dans Plesk p. 4);
  • DEPLOY_BACK_DEV_TOKEN — jeton pour dĂ©ployer dans le dĂ©pĂŽt de dĂ©veloppement sur le serveur.

Le processus de déploiement est simple et se compose de trois étapes principales :

  • construction et publication de l'image dans notre dĂ©pĂŽt ;
  • exĂ©cution des tests dans le conteneur Ă  partir de l'image rĂ©cemment construite ;
  • dĂ©ploiement dans l'environnement requis selon la branche (dev/master).

Frontend

Le fichier deploy.yml pour le dĂ©pĂŽt frontend diffĂšre peu de celui du backend. Il n'y a pas d'Ă©tape pour l'exĂ©cution des tests et les noms des jetons pour le dĂ©ploiement changent. Les secrets pour le dĂ©pĂŽt frontend, d'ailleurs, doivent ĂȘtre remplis sĂ©parĂ©ment.

Configuration du site

Proxy du trafic via Nginx

Eh bien, nous sommes arrivĂ©s Ă  la fin. Il ne reste plus qu'Ă  configurer le proxy du trafic entrant et sortant dans notre conteneur via Nginx. Ce processus a dĂ©jĂ  Ă©tĂ© abordĂ© au point 5 de la configuration du Docker Registry. La mĂȘme chose doit ĂȘtre rĂ©pĂ©tĂ©e pour les parties backend et frontend dans les environnements dev et prod.

Je vais fournir des captures d'écran des paramÚtres.

Backend

CI/CD dans Github Actions pour un projet Flask+Angular.

Frontend

CI/CD dans Github Actions pour un projet Flask+Angular.
Important Ă  prĂ©ciser. Dans le conteneur frontend, toutes les URL seront proxyĂ©es, sauf celles qui commencent par /api/ — elles seront proxyĂ©es dans le conteneur backend (donc dans le conteneur backend, tous les gestionnaires doivent commencer par /api/).

Résultats

Maintenant, notre site doit ĂȘtre accessible aux adresses helloworld.ru et dev.helloworld.ru (environnements prod et dev respectivement).

En résumé, nous avons appris comment préparer une simple application sur Flask et Angular et configurer un pipeline dans Github Actions pour son déploiement sur un serveur géré par Plesk.

Je vais redonner les liens vers les dépÎts avec le code : backend, frontend.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster