Site iconSite icon Anthony Jacob

Comment mettre en place CI/CD avec Docker et GitLab pour un projet Python

Salut !!

Dans les différentes entreprises que j’ai faites, toutes n’étaient pas au même niveau d’avancée technologique… Rares sont celles qui avaient mis en place des procédures de tests et de déploiement automatique en fonction des pushs sur GitLab.

La seule qui commençait à mettre ça en place pour certains projets ne concernait pas ceux sur lesquels je travaillais.

Et de mon côté, je n’échappe pas à cette règle : mes projets persos n’ont pas d’intégration continue.

Je vais résoudre ça dans cet article en mettant en place des règles de CI/CD avec un projet basique Python qui devra être déployé automatiquement avec Docker dès que du code sera envoyé et validé sur GitLab, sur ma branche main.

Prérequis

Pour les prérequis que je ne couvrirai pas dans cet article, j’ai déjà mis en place un runner GitLab que j’ai configuré, ainsi qu’un registry Docker privé.

Également, pour servir le projet en ligne, j’ai déjà un reverse proxy Apache et, bien sûr, j’ai configuré mon sous-domaine avec une entrée DNS correspondante sur OVH.

Créer un projet GitLab

Au niveau de GitLab, et pour la mise en place de mon exemple, je crée un projet GitLab basique.

Créer un projet Python Flask basique

Le projet GitLab créé plus haut va me servir à pousser le code de mon projet Python. Dans mon cas, et pour l’exemple, je vais faire un projet simple avec Python et le framework Flask.

Je vais donc initialiser mon projet en clonant le dépôt vide dans mon dossier de travail:

Je me rends ensuite dans le dossier et je crée un environnement virtuel Python:

J’active mon venv (sur Windows) avec la commande:

J’installe Flask:

J’en profite pour exclure les dossiers venv et __pycache__ de mes fichiers à commit avec un fichier .gitignore:

Ensuite, je crée le dossier app, dans lequel j’ajoute un fichier vide __init__.py et le fichier principal de mon application app.py:

Je teste ensuite l’application en local avec:

Tout roule pour l’instant

Pour préparer la suite, je vais aussi utiliser le server Waitress. Je commence par l’installer, toujours dans mon venv:

Et je le teste avec:

Là encore, tout roule:

Créer une base de test Unitaire simple

Ici, je vais créer un test unitaire d’une fonction pour valider le code et, dans notre cas ici, ce test nous servira plus tard de validation avant le déploiement.

Je commence par installer pytest :

Dans le répertoire de mon projet, je crée un fichier de configuration pour pytest (pytest.ini) et un nouveau dossier tests, dans lequel je crée le fichier principal de mon test test_app.py:

Voilà de quoi tester l’unique fonction de ce projet de test.

Pour lancer les tests, je lance pytest depuis le répertoire racine de mon projet:

Si je change le retour de ma fonction hello_world(), mon test est bien en erreur:

Exporter les dépendances Python

À ce stade, j’ai tout ce qu’il faut pour exporter la liste des dépendances Python de mon projet avec :

Préparer l’image Docker

Le projet tourne, les tests sont en place, on peut maintenant s’attaquer à l’image Docker. Pour ça, je crée un fichier Dockerfile dans un nouveau dossier docker:

Et je lance waitress dans mon entrypoint.sh

Je vais tester mon image en local, donc je build l’image avec:

pour finir, je la lance ensuite avec:

Tout est bon, mon container docker est lancé et mon application est bien servi sur le port 8181:

Commit initial sur le dépôt GitLab

Pour rappel, avec les étapes que j’ai effectuées, la structure de mon projet ressemble à ça:

Voilà une base que je peux pousser sur le dépôt GitLab avec :

Préparer l’hôte pour le déploiement

Pour déployer automatiquement mon projet depuis mon serveur, je vais indiquer à mon job GitLab de se connecter en SSH à mon serveur et déployer mon conteneur Docker.

Pour ça, je vais créer un utilisateur autodeploy sur mon hôte, qui pourra se connecter uniquement en ssh. J’ajoute l’utilisateur sur le système :

je vais ensuite initialiser les répertoires ssh:

Puis, je génère une paire de clés RSA publique/privée:

J’ajoute ensuite cette clé comme valide et autorisée pour que l’utilisateur autodeploy puisse se connecter avec SSH:

On n’oublie pas de définir les bonnes autorisations pour les fichiers:

J’ajoute ensuite l’utilisateur au groupe docker pour qu’il puisse l’exécuter sans problème:

Configuration de GitLab CI/CD

On attaque maintenant et enfin le cœur du sujet : la configuration de GitLab.

Pour rappel, dans cet article, mon but est, à chaque commit sur la branche de développement, de tester mon projet et, si les tests passent, de build mon image Docker, de la pousser sur mon registry Docker privé et de la déployer automatiquement dans mon environnement de « préprod ».

Je vais avoir besoin de définir quelques variables pour l’exécution de ma pipeline :

GitLab prend par défaut le fichier de configuration .gitlab-ci.yml:

Je crée ma branche de développement develop:

Puis, je crée un fichier .gitlab-ci.yml à la racine du projet. Ci-dessous, mon fichier final après quelques itérations :

Dans les grandes lignes, j’ai 4 phases:

Il ne me reste plus qu’à pousser mon code sur GitLab

Et je peux admirer ma pipeline qui se déroule sans accroc (presque du premier coup…):

Pour enfin avoir le tant attendu projet déployé automatiquement:

Et bien sûr, si les étapes de pytest ou de lint échouent, il n’y a pas de nouvelle version déployée.

Voilà, encore une histoire de 5 minutes qui s’est transformée en quelques heures !

En tout cas, si tu passes par là, j’espère que ce contenu pourra t’être utile. N’hésite pas à me faire un retour. En attendant, je te dis à bientôt pour de prochaines aventures !

Partagez l'article:
Quitter la version mobile