
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 : , .
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.
В il existe un fichier Readme.md avec une description détaillée de la structure et des instructions pour exécuter le projet.
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.
encore plus facile, il n'y a qu'un seul problème send_mail_task.
Dans le dossier il y a deux sous-dossiers :
dockeravec deux Dockerfiles (base.dockerfilepour construire une image de base qui change rarement etDockerfilepour 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.ymlcréer une base de données locale pour le développement;docker-compose.local.workers.ymlpour la relance locale du travailleur, base de données, Redis et RabbitMQ ;docker-compose.test.ymlexécuter des tests pendant le déploiement ;docker-compose.ymlpour le déploiement.
Et le dernier dossier qui nous intéresse - . 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
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 :

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 :
Dockergérer et afficher visuellement l'état des conteneurs dans le panneau d'administration de Plesk ;Gitconfigurer l'étape de déploiement sur le serveur ;Let's Encryptpour générer (et renouveler automatiquement) des certificats TLS gratuits ;Firewallpour configurer le filtrage du trafic entrant.
Vous pouvez les installer via le panneau d'administration de Plesk dans la section Extensions :

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.
- Créez un abonnement pour le domaine helloworld.ru et spécifiez le mot de passe de connexion pour l'utilisateur système :

Cochez la case en bas de la page Sécurisez le domaine avec Let's Encryptsi nous voulons configurer HTTPS pour le site :
- Ensuite, dans cet abonnement, créez un sous-domaine dev.helloworld.ru (pour lequel vous pouvez également émettre un certificat TLS gratuit) :

Installation des composants du serveur
Nous avons un serveur avec OS Debian Étirement 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 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.
Instructions détaillées pour l'installation de Postgres sur Debian Il y en a plein sur Internet (), 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 : 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 maintenant à l'installation de RabbitMQ, un courtier de messages pour Celery. Il est installé sur Debian C'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.
- Nous allons dans Plesk, allons dans la section Extensions, cherchons l'extension Docker et installons-la (nous avons besoin d'une version gratuite) :

- Accédez à l'extension installée, trouvez l'image via la recherche
redis bitnamiet installez la dernière version :
- 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 :

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

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 :
- référentiel Docker protégé par mot de passe accessible sur un sous-domaine ;
- Interface utilisateur pour afficher les images dans le référentiel, disponible sur .
Pour ce faire:
- 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.
- Ajoutez le fichier au dossier du sous-domaine docker.helloworld.ru
docker-compose.ymlavec 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' - 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 - Collecter et soulever les conteneurs :
docker-compose up -d - 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:

Et ajoutez une règle pour diriger le trafic entrant vers notre conteneur :

- 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 - Vérifions également le fonctionnement du sous-domaine docker-ui.helloworld.ru :

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) :
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.
- Nous passons à Outils & Paramètres > Paramètres > Pare-feu:

- 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
- Nous ajouterons également une règle qui ouvrira les ports PostgreSQL et les panneaux de gestion RabbitMQ au monde extérieur :

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

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.
- Nous allons à l'abonnement de notre site Web Helloworld et allons à la sous-section Git :

- 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):
- Copiez la clé publique SSH de l'étape précédente et c'est dans les paramètres de Github.
- 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):
- 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 casprod;
{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 - 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 .
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 : : 8443 ou :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
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

L'extrémité avant

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