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

CI/CD dans Github Actions pour un projet Flask+Angular
Dans cet article, je partagerai mon expérience de configuration de CI/CD à l'aide du panneau de contrôle Plesk et des actions Github. Aujourd'hui, nous allons apprendre à déployer un projet simple avec le nom simple "Helloworld". Il est écrit dans le framework Flask Python, avec des workers Celery et une interface Angular 8.

Liens vers les dépôts : backend, l'extrémité avant.

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

Dans la troisième partie, nous verrons enfin comment mettre en place un pipeline pour déployer notre projet sur un serveur dans un environnement dev et prod. Et puis nous lancerons le site sur le serveur.

Et 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 hypothécaires chez Domclick.

Aperçu du projet

Examinons d'abord deux référentiels de projet - backend et front - et passons en revue le code.

Backend : flacon + céleri

Pour la partie arrière, j'ai pris un tas assez populaire parmi les développeurs Python : le framework Flask (pour l'API) et Celery (pour la file d'attente des tâches). SQLAchemy est utilisé comme ORM. L'alambic est utilisé pour les migrations. Pour la validation JSON dans les poignées - Marshmallow.

В référentiels il existe un fichier Readme.md avec une description détaillée de la structure et des instructions pour exécuter le projet.

API de composant WebPart assez simple, se compose de 6 stylos :

  • /ping - pour vérifier la disponibilité ;
  • poignées pour l'enregistrement, l'autorisation, la désautorisation et l'obtention d'un utilisateur autorisé ;
  • un descripteur de messagerie qui place une tâche dans la file d'attente Celery.

Partie de céleri encore plus facile, il n'y a qu'un seul problème send_mail_task.

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

  • docker avec deux Dockerfiles (base.dockerfile pour construire une image de base qui change rarement et Dockerfile pour les ensembles principaux) ;
  • .env_files - avec des fichiers avec des variables d'environnement pour différents environnements.

Il y a quatre fichiers docker-compose à la racine du projet :

  • docker-compose.local.db.yml créer une base de données locale pour le développement;
  • docker-compose.local.workers.yml pour la relance locale du travailleur, base de données, Redis et RabbitMQ ;
  • docker-compose.test.yml exécuter des tests pendant le déploiement ;
  • docker-compose.yml pour le déploiement.

Et le dernier dossier qui nous intéresse - .ci-cd. Il contient des scripts shell pour le déploiement :

  • deploy.sh — lancement de la migration et du déploiement. S'exécute sur le serveur après la création et l'exécution de tests dans Github Actions ;
  • rollback.sh - restauration des conteneurs à la version précédente de l'assemblage ;
  • curl_tg.sh - envoyer des notifications de déploiement à Telegram.

Interface sur Angular

Référentiel avec façade beaucoup plus simple que celui de Beck. Le recto se compose de trois pages :

  • Page principale avec un formulaire d'envoi d'e-mail et un bouton de sortie.
  • Page de connexion.
  • Page d'inscription.

La page principale semble ascétique :

CI/CD dans Github Actions pour un projet Flask+Angular
Il y a deux fichiers à la racine Dockerfile и docker-compose.yml, ainsi que le dossier familier .ci-cd avec un peu moins de scripts que dans le référentiel arrière (suppression des scripts pour l'exécution des tests).

Démarrer un projet dans Plesk

Commençons par configurer Plesk et créer un abonnement pour notre site.

Installation d'extensions

Dans Plesk, nous avons besoin de quatre extensions :

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

Vous pouvez les installer via le panneau d'administration de Plesk dans la section Extensions :

CI/CD dans Github Actions pour un projet Flask+Angular
Nous ne considérerons pas les paramètres détaillés des extensions, les paramètres par défaut suffiront pour nos besoins de démonstration.

Créer un abonnement et un site

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

  1. Créez un abonnement pour le domaine helloworld.ru et spécifiez le mot de passe de connexion pour l'utilisateur système :

    CI/CD dans Github Actions pour un projet Flask+Angular
    Cochez la case en bas de la page Sécurisez le domaine avec Let's Encryptsi nous voulons configurer HTTPS pour le site :

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

  2. Ensuite, dans cet abonnement, créez un sous-domaine dev.helloworld.ru (pour lequel vous pouvez également émettre un certificat TLS gratuit) :

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

Installation des composants du serveur

Nous avons un serveur avec SE Debian Stretch 9.12 et panneau de contrôle installé Plesk Obsidienne 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 (identique, même instance avec différents vhosts pour les environnements).
  • Deux instances Redis (pour les environnements de développement et de production).
  • Registre Docker (pour le stockage local des images Docker construites).
  • Interface utilisateur pour le registre Docker.

PostgreSQL

Plesk est déjà fourni avec le SGBD PostgreSQL, mais pas la dernière version (au moment de la rédaction de Plesk Obsidian soutenu versions 8.4 à 10.8 de Postgres). Nous voulons la dernière version de notre application (12.3 au moment d'écrire ces lignes), nous allons donc l'installer manuellement.

Il existe de nombreuses instructions détaillées pour installer Postgres sur Debian sur le net (exemple), donc je ne les décrirai pas en détail, je donnerai juste 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

Considérant que PostgreSQL a des paramètres par défaut plutôt médiocres, il est nécessaire de corriger la configuration. Cela nous aidera calculatrice: vous devez entrer les paramètres de votre serveur et remplacer les paramètres dans le fichier /etc/postgresql/12/main/postgresql.confà ceux offerts. Il convient de noter ici que de telles calculatrices ne sont pas une solution miracle et que la base doit être réglée plus précisément, en fonction de votre matériel, de votre application et de la complexité de vos requêtes. Mais cela suffit pour commencer.

En plus des réglages proposés par le calculateur, on change aussi en postgresql.confle port par défaut 5432 à un autre (dans notre exemple - 53983).

Après avoir modifié le fichier de configuration, redémarrez postgresql-server avec la commande :

service postgresql restart

Nous avons installé et configuré PostgreSQL. Créons maintenant une base de données, des utilisateurs pour les environnements de développement et de production, et donnons aux utilisateurs le droit de gérer 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, un courtier de messages pour Celery. L'installer sur Debian est assez simple :

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, utilisateurs et accordez 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

Installons et configurons maintenant le dernier composant de notre application - Redis. Il sera utilisé comme backend pour stocker les résultats des tâches Celery.

Nous allons élever deux conteneurs Docker avec Redis pour les environnements de développement et de production en utilisant l'extension Docker pour Plesk.

  1. Nous allons dans Plesk, allons dans la section Extensions, cherchons l'extension Docker et installons-la (nous avons besoin d'une version gratuite) :

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

  2. Accédez à l'extension installée, trouvez l'image via la recherche redis bitnami et installez la dernière version :

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

  3. Nous entrons dans le conteneur téléchargé et ajustons la configuration : spécifiez 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. Nous effectuons les étapes 2-3 pour le conteneur prod, dans les paramètres nous ne modifions que les paramètres : port, mot de passe, taille de la RAM et chemin vers le dossier du volume sur le serveur :

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

Registre Docker

En plus des services de base, il serait bien de mettre votre propre référentiel d'images Docker sur le serveur. Heureusement, l'espace serveur est maintenant assez bon marché (certainement moins cher qu'un abonnement DockerHub), et le processus de mise en place d'un référentiel privé est très simple.

Nous voulons avoir :

Pour ce faire:

  1. Créons deux sous-domaines dans Plesk dans notre abonnement : docker.helloworld.ru et docker-ui.helloworld.ru, et configurons les certificats Let's Encrypt pour eux.
  2. Ajoutez le fichier au dossier du sous-domaine docker.helloworld.ru docker-compose.yml avec un contenu comme celui-ci :
    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. Sous SSH, nous allons générer le fichier .htpasswd pour l'autorisation Basic dans le référentiel Docker :
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Collecter et soulever les conteneurs :
    docker-compose up -d
  5. Et nous devons rediriger Nginx vers nos conteneurs. Cela peut être fait via Plesk.

Les étapes suivantes doivent être effectuées pour les sous-domaines docker.helloworld.ru et docker-ui.helloworld.ru :

Dans la section Outils de développement notre site aller à Règles de proxy Docker:

CI/CD dans Github Actions pour un projet Flask+Angular
Et ajoutez une règle pour diriger le trafic entrant vers notre conteneur :

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

  1. Nous vérifions que nous pouvons nous connecter à notre conteneur depuis la machine 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. Vérifions également le fonctionnement du sous-domaine docker-ui.helloworld.ru :

    CI/CD dans Github Actions pour un projet Flask+Angular
    Lorsque vous cliquez sur Parcourir les référentiels, le navigateur affiche une fenêtre d'autorisation dans laquelle vous devrez saisir le nom d'utilisateur et le mot de passe du référentiel. Après cela, nous serons transférés sur une page avec une liste de dépôts (pour l'instant, elle sera vide pour vous) :

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

Ouvrir des ports dans Plesk Firewall

Après avoir installé et configuré les composants, nous devons ouvrir des ports afin que les composants soient accessibles depuis les conteneurs Docker et le réseau externe.

Voyons comment faire cela en utilisant l'extension Firewall pour Plesk que nous avons installée plus tôt.

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

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

  3. Nous ajouterons également une règle qui ouvrira les ports PostgreSQL et les panneaux de gestion RabbitMQ au monde extérieur :

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

  4. Appliquez les règles à l'aide du bouton Apply Changes :

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

Configuration de CI/CD dans Github Actions

Passons à la partie la plus intéressante - la mise en place d'un pipeline d'intégration continue et la livraison de notre projet au serveur.

Ce pipeline sera composé de deux parties :

  • construire une image et exécuter des tests (pour le backend) - côté Github ;
  • exécuter des migrations (pour le backend) et déployer des conteneurs - sur le serveur.

Déployer sur Plesk

Traitons d'abord le deuxième point (car le premier en dépend).

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

Prenons un exemple avec un environnement Prod pour un référentiel Backend.

  1. Nous allons à l'abonnement de notre site Web Helloworld et allons à la sous-section Git :

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

  2. Insérez un lien vers notre référentiel Github dans le champ "Remote Git repository" et modifiez le dossier par défaut httpdocs à un autre (ex. /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 ajouter c'est dans les paramètres de Github.
  4. Cliquez sur OK sur l'écran de l'étape 2, après quoi nous serons redirigés vers la page du référentiel dans Plesk. Nous devons maintenant configurer le référentiel pour qu'il soit mis à jour lors des commits sur la branche master. Pour ce faire, rendez-vous sur Paramètres du référentiel et enregistrer la valeur Webhook URL (nous en aurons besoin plus tard lors de la configuration des actions Github):

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

  5. Dans le champ Actions de l'écran du paragraphe 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 d'accès au dossier prod du référentiel backend sur le serveur ;
    {ENV} - environnement (dev/prod), dans notre cas prod;
    {DOCKER_REGISTRY_HOST} - l'hébergeur de notre référentiel docker
    {TG_BOT_TOKEN} — Jeton de bot Telegram ;
    {TG_CHAT_ID} — ID du chat/canal pour envoyer des notifications.

    Exemple de scénario :

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

L'environnement de développement pour le référentiel backend et le frontend sont configurés 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 fichier deploy.yml.

Mais avant de l'analyser, remplissons les variables secrètes dont nous avons besoin dans Github. Pour ce faire, rendez-vous sur Paramètres -> Secrets:

  • DOCKER_REGISTRY - l'hébergeur de notre référentiel Docker (docker.helloworld.ru) ;
  • DOCKER_LOGIN - connectez-vous au référentiel Docker ;
  • DOCKER_PASSWORD - mot de passe pour cela;
  • DEPLOY_HOST — hébergeur où le panneau d'administration de Plesk est disponible (exemple : helloworld.com: 8443 ou 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN - un jeton pour le déploiement vers le prod-repository sur le serveur (nous l'avons obtenu dans Déploiement dans Plesk p. 4) ;
  • DEPLOY_BACK_DEV_TOKEN - jeton pour le déploiement dans le référentiel dev sur le serveur.

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

  • construire et publier l'image dans notre référentiel ;
  • exécuter des tests dans un conteneur basé sur une image fraîchement construite ;
  • déploiement dans l'environnement souhaité en fonction de la branche (dev/master).

L'extrémité avant

Le fichier deploy.yml pour le référentiel frontal peu différent de Beck. Il manque une étape avec l'exécution des tests et change les noms des jetons pour le déploiement. Soit dit en passant, les secrets du référentiel frontal 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 proxying du trafic entrant et sortant vers notre conteneur via Nginx. Nous avons déjà couvert ce processus à l'étape 5 de la configuration de Docker Registry. La même chose doit être répétée pour les parties arrière et avant dans les environnements de développement et de production.

Je fournirai des captures d'écran des paramètres.

backend

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

L'extrémité avant

CI/CD dans Github Actions pour un projet Flask+Angular
Clarification importante. Toutes les URL seront transmises par proxy au conteneur frontal, à l'exception de celles commençant par /api/ - ils seront transmis par procuration au conteneur arrière (donc dans le conteneur arrière, tous les manutentionnaires doivent commencer par /api/).

Les résultats de

Maintenant, notre site devrait être disponible sur helloworld.ru et dev.helloworld.ru (environnements de production et de développement, respectivement).

Au total, nous avons appris à préparer une application simple dans Flask et Angular et à mettre en place un pipeline dans Github Actions pour la déployer sur un serveur exécutant Plesk.

Je vais dupliquer les liens vers les dépôts avec le code : backend, l'extrémité avant.

Source: habr.com

Ajouter un commentaire