Mise en place d'une chaîne CI/CD complète avec GitLab CI pour une stack Spring Boot/Angular Dockerisée
Dans le paysage technologique actuel, l'intégration et le déploiement continus (CI/CD) sont devenus des piliers essentiels pour livrer des logiciels de haute qualité avec rapidité et fiabilité. Pour les applications modernes basées sur des microservices ou des architectures polyglottes, la combinaison de frameworks robustes comme Spring Boot pour le backend et Angular pour le frontend, couplée à la conteneurisation avec Docker, représente une stack puissante. L'automatisation du cycle de vie de développement via un outil comme GitLab CI permet d'orchestrer l'ensemble du processus, depuis la validation du code jusqu'au déploiement en production.
Cet article se propose d'explorer en détail la mise en place d'une chaîne CI/CD complète et automatisée en utilisant GitLab CI. Il sera démontré comment construire, tester, et déployer une application Spring Boot et une application Angular, toutes deux conteneurisées avec Docker, afin de garantir un processus de livraison logicielle fluide et efficace. Les développeurs Full Stack, et plus particulièrement ceux qui manient Java Spring Boot et Angular, comme Laty Gueye Samba, Développeur Full Stack à Dakar, trouveront dans cette approche une méthode robuste pour gérer leurs projets.
L'objectif est de présenter une architecture CI/CD qui non seulement automatise les tâches répétitives mais assure également la cohérence de l'environnement, réduit les erreurs humaines et accélère la mise sur le marché des fonctionnalités. La maîtrise de ces outils est un atout majeur pour tout développeur désireux d'optimiser ses flux de travail.
Prérequis et Architecture Générale de la Chaîne CI/CD
Avant de plonger dans la configuration de GitLab CI, il est essentiel de comprendre les composants de l'architecture. Une application typique Spring Boot/Angular Dockerisée est composée de deux services distincts : un backend Java Spring Boot et un frontend Angular, chacun ayant son propre Dockerfile. Ces deux services sont ensuite intégrés pour fonctionner ensemble. Pour la CI/CD, GitLab CI sera le chef d'orchestre, utilisant des Runners Docker pour exécuter les tâches de build, de test et de déploiement.
Les prérequis incluent un dépôt GitLab hébergeant le code source des applications Spring Boot et Angular (potentiellement dans des sous-dossiers d'un même dépôt monolithique ou dans des dépôts séparés pour une architecture microservices), ainsi qu'un ou plusieurs GitLab Runners configurés. Il est fortement recommandé d'utiliser des GitLab Runners avec l'exécuteur Docker ou Kubernetes pour faciliter la conteneurisation et l'isolation des tâches. La chaîne de CI/CD sera définie dans un fichier .gitlab-ci.yml à la racine du dépôt.
Une architecture CI/CD complète impliquera généralement les étapes suivantes, définies comme des stages dans GitLab CI :
- Build : Compilation du code source des applications Spring Boot et Angular.
- Test : Exécution des tests unitaires et d'intégration pour les deux applications.
- Docker Build : Construction des images Docker pour le backend Spring Boot et le frontend Angular.
- Docker Push : Pousser les images Docker vers un registre de conteneurs (par exemple, le Container Registry de GitLab).
- Deploy : Déploiement des nouvelles versions sur un environnement cible (staging, production).
Voici une ébauche de la structure d'un fichier .gitlab-ci.yml :
stages:
- build
- test
- docker_build
- docker_push
- deploy_staging
- deploy_production
# Définition des services nécessaires (ex: Docker in Docker)
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_TLS_CERTDIR: ""
services:
- docker:dind
Intégration CI/CD pour Spring Boot et Angular Dockerisés
Chaque composant de la stack (Spring Boot et Angular) nécessitera des étapes spécifiques dans le pipeline GitLab CI pour son build, ses tests et sa conteneurisation. L'objectif est de s'assurer que chaque application est prête à être empaquetée dans une image Docker avant le déploiement.
Backend Spring Boot
Pour l'application Spring Boot, le processus implique généralement la compilation avec Maven ou Gradle, l'exécution des tests JUnit, puis la construction d'une image Docker qui encapsule l'application JAR.
# Job de build pour Spring Boot
build_backend:
stage: build
image: maven:3.8.7-openjdk-17 # Ou une image Gradle
script:
- echo "Début du build Spring Boot..."
- mvn clean package -DskipTests
artifacts:
paths:
- backend/target/*.jar
expire_in: 1 week
# Job de test pour Spring Boot
test_backend:
stage: test
image: maven:3.8.7-openjdk-17
script:
- echo "Exécution des tests Spring Boot..."
- mvn test
dependencies:
- build_backend
# Job Docker Build et Push pour Spring Boot
docker_build_push_backend:
stage: docker_build
image: docker:20.10.16
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- docker build -t "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" -f backend/Dockerfile backend/.
- docker push "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA"
- echo "Image Docker Spring Boot poussée : $CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA"
only:
- main
dependencies:
- build_backend
Frontend Angular
Pour l'application Angular, les étapes sont similaires : installation des dépendances Node.js, compilation du projet, exécution des tests unitaires (Karma/Jasmine), et enfin la construction de l'image Docker contenant l'application compilée et servie par un serveur web léger comme Nginx.
# Job de build pour Angular
build_frontend:
stage: build
image: node:16 # Ou une version Node.js appropriée
script:
- echo "Début du build Angular..."
- cd frontend
- npm install
- npm run build -- --configuration=production
artifacts:
paths:
- frontend/dist/
expire_in: 1 week
# Job de test pour Angular
test_frontend:
stage: test
image: node:16
script:
- echo "Exécution des tests Angular..."
- cd frontend
- npm install
- npm run test -- --watch=false --browsers=ChromeHeadless
dependencies:
- build_frontend
# Job Docker Build et Push pour Angular
docker_build_push_frontend:
stage: docker_build
image: docker:20.10.16
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- docker build -t "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA" -f frontend/Dockerfile frontend/.
- docker push "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA"
- echo "Image Docker Angular poussée : $CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA"
only:
- main
dependencies:
- build_frontend
Déploiement Continu et Bonnes Pratiques
Le déploiement est la dernière étape cruciale. Il s'agit de prendre les images Docker construites et de les déployer sur un environnement cible. Cela peut impliquer l'utilisation de SSH pour se connecter à un serveur distant, l'exécution de commandes Docker pour arrêter les anciens conteneurs et démarrer les nouveaux, ou l'orchestration via Docker Compose, Kubernetes, etc. Pour un exemple simple, un déploiement sur un serveur unique via SSH peut être illustré.
deploy_staging:
stage: deploy_staging
image: alpine/git
before_script:
- apk add openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -H "$STAGING_SERVER_IP" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- ssh "$STAGING_SERVER_USER@$STAGING_SERVER_IP" "
docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY" &&
docker pull "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" &&
docker pull "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA" &&
docker stop my_backend my_frontend || true &&
docker rm my_backend my_frontend || true &&
docker run -d --name my_backend -p 8080:8080 "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" &&
docker run -d --name my_frontend -p 80:80 "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA"
"
environment:
name: staging
url: http://$STAGING_SERVER_IP
only:
- main
deploy_production:
stage: deploy_production
image: alpine/git
when: manual # Déploiement manuel en production
before_script:
- apk add openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY_PROD" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -H "$PRODUCTION_SERVER_IP" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- ssh "$PRODUCTION_SERVER_USER@$PRODUCTION_SERVER_IP" "
docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY" &&
docker pull "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" &&
docker pull "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA" &&
docker stop my_backend my_frontend || true &&
docker rm my_backend my_frontend || true &&
docker run -d --name my_backend -p 8080:8080 "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" &&
docker run -d --name my_frontend -p 80:80 "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA"
"
environment:
name: production
url: https://$PRODUCTION_DOMAIN
only:
- main
Il est crucial de sécuriser les informations sensibles comme les clés SSH et les identifiants de registre Docker en utilisant les variables CI/CD de GitLab (variables masquées et protégées).
Point de vue : développeur full stack à Dakar
Pour un développeur travaillant sur des systèmes comme des applications de gestion des risques ou des systèmes ERP complexes, la maîtrise de l'intégration et du déploiement continus représente un avantage concurrentiel réel sur le marché technologique africain, en pleine expansion. Laty Gueye Samba, Développeur Full Stack à Dakar, reconnaît l'importance de ces pratiques pour garantir la robustesse et l'évolutivité des solutions logicielles, permettant une livraison plus rapide et plus fiable des innovations.
Conclusion
La mise en place d'une chaîne CI/CD complète avec GitLab CI pour une stack Spring Boot/Angular Dockerisée est un investissement stratégique qui se traduit par une amélioration significative de la qualité logicielle, une réduction des délais de mise sur le marché et une plus grande sérénité pour les équipes de développement. En automatisant les processus de build, de test et de déploiement, les développeurs peuvent se concentrer sur l'écriture de code de valeur, sachant que la livraison sera gérée de manière cohérente et efficace.
Pour des développeurs Full Stack comme Laty Gueye Samba, basé à Dakar et expert en Java Spring Boot et Angular, l'adoption de ces méthodologies est non seulement une preuve de professionnalisme mais aussi un levier puissant pour adresser les défis complexes des applications métier modernes. Cette approche permet de construire des systèmes robustes, prêts à s'adapter aux besoins changeants des entreprises, depuis les projets de gestion hospitalière jusqu'aux applications métier complexes.
Pour approfondir les concepts abordés, il est recommandé de consulter les ressources officielles :
À propos de l'auteur
Laty Gueye Samba est développeur Full Stack basé à Dakar, Sénégal. Spécialiste des écosystèmes Java / Spring Boot et Angular.
Contact : latygueyesamba@gmail.com | Dakar, Sénégal