Automatisation du déploiement continu d'une application Spring Boot/Angular avec GitLab CI/CD et Docker
Ce billet technique présente une approche pragmatique pour automatiser le build, la containerisation et le déploiement d'une application composée d'un backend Spring Boot et d'un frontend Angular. L'objectif est d'exposer une pipeline GitLab CI/CD robuste, sécurisée et reproductible, prête à pousser des images vers le registre GitLab et à déployer vers un environnement de production (hôte Docker ou Kubernetes).
Architecture et principes
L'architecture adoptée sépare clairement les responsabilités : compilation et tests pour chaque application (backend et frontend), production d'artefacts, construction d'images Docker optimisées et déploiement automatisé. La pipeline suit des étapes classiques : build, test, dockerize et deploy. Les secrets et credentials sont gérés via les variables CI/CD de GitLab.
Prérequis
Avant d'implémenter la pipeline, vérifier les éléments suivants :
- Un repository GitLab hébergeant les sources backend et frontend.
- GitLab Runner configuré (executor Docker recommandé) avec service docker:dind si la pipeline construit des images Docker.
- Variables CI/CD définies : CI_REGISTRY, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD (ou utilisation de $CI_JOB_TOKEN), clés SSH pour déploiement via SSH ou credentials Kubernetes.
Exemples de Dockerfile
Dockerfile multi-stage pour Spring Boot (optimisé pour construire l'artefact et produire une image d'exécution minimaliste) :
FROM maven:3.8.6-openjdk-11 as builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -B -DskipTests package
FROM openjdk:11-jre-slim
ARG JAR_FILE=/app/target/*.jar
COPY --from=builder /app/target/app.jar /opt/app/app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/opt/app/app.jar"]
Dockerfile multi-stage pour Angular (build avec Node puis service statique via Nginx) :
FROM node:16-alpine as build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build -- --prod
FROM nginx:alpine
COPY --from=build /usr/src/app/dist/your-app-name /usr/share/nginx/html
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
Fichier .gitlab-ci.yml recommandé
Exemple de pipeline qui compile, archive, construit des images et pousse vers le registre GitLab. Le pipeline utilise le service docker:dind pour la phase de création d'images.
stages:
- build
- test
- dockerize
- deploy
build_backend:
image: maven:3.8.6-openjdk-11
stage: build
script:
- mvn -B -DskipTests package
artifacts:
paths:
- backend/target/*.jar
expire_in: 1 hour
build_frontend:
image: node:16-alpine
stage: build
script:
- cd frontend
- npm ci
- npm run build -- --prod
artifacts:
paths:
- frontend/dist
expire_in: 1 hour
docker_build:
image: docker:24
services:
- docker:24-dind
stage: dockerize
variables:
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
script:
- docker build -t "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" -f backend/Dockerfile ./backend
- docker build -t "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA" -f frontend/Dockerfile ./frontend
- docker push "$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA"
- docker push "$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA"
only:
- main
- master
deploy_production:
image: bitnami/kubectl:1.27
stage: deploy
script:
- kubectl config set-cluster production --server="$K8S_API_URL"
- kubectl config set-credentials gitlab --token="$K8S_TOKEN"
- kubectl config set-context production --cluster=production --user=gitlab
- kubectl config use-context production
- kubectl set image deployment/backend backend="$CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA" --namespace=prod
- kubectl set image deployment/frontend frontend="$CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA" --namespace=prod
only:
- tags
Remarque : pour un déploiement sur un hôte Docker classique, remplacer la section deploy par un job utilisant SSH (clé privée stockée en variable protégée) et exécuter des commandes docker pull, docker-compose up -d ou des instructions d'update.
Meilleures pratiques et recommandations
- Utiliser des builds multi-stage pour réduire la taille des images et séparer les phases de compilation et d'exécution.
- Stocker les secrets dans les variables protégées GitLab CI/CD et limiter l'accès aux branches protégées.
- Employer des tags d'images immuables ($CI_COMMIT_SHORT_SHA) pour permettre le roll-back.
- Activer le scanning d'images et les scans de dépendances (SAST, DAST) proposés par GitLab pour améliorer la sécurité.
- Cacher les répertoires Maven et npm entre jobs si besoin pour accélérer les builds.
Validation et rollbacks
Inclure des jobs de tests unitaires et d'intégration dans les étapes de build réduit les risques. Pour le déploiement, une stratégie de mise à jour progressive (blue/green ou rolling update via Kubernetes) permet de minimiser les interruptions. L'utilisation de tags d'image immuables facilite le rollback en déployant une image antérieure connue.
Conclusion
La combinaison Spring Boot, Angular, Docker et GitLab CI/CD permet de construire une chaîne d'automatisation fiable et reproductible. En suivant des pratiques de containerisation optimisée, en gérant correctement les secrets et en définissant des pipelines modulaires, le développeur obtient un flux d'intégration et de déploiement continu sécurisé et maintenable.
À 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