Retour aux articles

Mise en place d'une chaîne CI/CD complète avec GitLab CI pour une stack Spring Boot/Angular Dockerisée

Mise en place d'une chaîne CI/CD complète avec GitLab CI pour une stack Spring Boot/Angular Dockerisée | Laty Gueye Samba - Développeur Full Stack Dakar Sénégal, Expert Java Spring Boot Angular

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