Déploiement continu d'applications Full Stack (Spring Boot & Angular) avec Docker et GitLab CI/CD
Cet article présente une approche pragmatique pour automatiser le déploiement continu d'une application Full Stack composée d'un backend Spring Boot et d'un frontend Angular. L'accent est mis sur la conteneurisation avec Docker, l'intégration avec le registre de conteneurs de GitLab et l'orchestration du pipeline GitLab CI/CD pour construire, tester, publier et déployer automatiquement les images.
Architecture cible
La solution s'articule autour des éléments suivants :
- Spring Boot : API REST packagée en JAR exécuté dans un conteneur.
- Angular : application front compilée en assets statiques servis par Nginx.
- Docker : images multi-stage pour optimiser la taille et la sécurité.
- GitLab CI/CD : pipeline pour construire, tester, pousser et déployer.
- GitLab Container Registry : stockage des images Docker intégrée au dépôt.
Principes clés
Plusieurs principes garantissent un pipeline robuste :
- Build reproductible via images d'outils (Maven/Node).
- Multi-stage builds pour séparer compilation et runtime.
- Tests automatisés exécutés avant toute publication d'image.
- Secrets gérés via variables CI/CD et secrets de registre.
- Déploiement idempotent (docker-compose pull / up, ou Kubernetes).
Dockerisation : Spring Boot (exemple Maven)
Un Dockerfile multi-stage permet de construire l'artefact puis de le lancer dans une image légère :
FROM maven:3.8.7-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -B -DskipTests clean package
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
EXPOSE 8080
COPY --from=build /app/target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app/app.jar"]
Remarques : activer les tests dans une étape distincte si le pipeline impose des contrôles stricts. Utiliser une image JRE minimale pour réduire la surface d'attaque.
Dockerisation : Angular
Pour Angular, un build Node puis la distribution via Nginx est recommandé :
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build -- --prod
FROM nginx:stable-alpine
COPY --from=build /app/dist/your-app /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Remarques : vérifier les headers de sécurité (CSP, HSTS) via la configuration Nginx si nécessaire.
docker-compose pour le développement local
Un fichier docker-compose simplifie l'exécution locale :
version: '3.8'
services:
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=dev
frontend:
build: ./frontend
ports:
- "4200:80"
depends_on:
- backend
Cela permet de simuler l'environnement de production tout en restant simple à lancer pour l'équipe.
Pipeline GitLab CI/CD : principes et variables
Le pipeline typique comprend les étapes : build, test, image, release et deploy. Utiliser les variables CI/CD et les variables protégées pour
- authentifier le registre :
CI_REGISTRY,CI_REGISTRY_IMAGE,CI_JOB_TOKEN - stockage des secrets : clés SSH, tokens d'API, certificats
Exemple minimal .gitlab-ci.yml
image: docker:24.0.2
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: ""
MAVEN_OPTS: "-Xmx1024m"
stages:
- build
- test
- image
- deploy
cache:
paths:
- .m2/repository
build_backend:
stage: build
image: maven:3.8.7-openjdk-17
script:
- mvn -B -DskipTests clean package
artifacts:
paths:
- backend/target/*.jar
test_backend:
stage: test
image: maven:3.8.7-openjdk-17
script:
- mvn test
build_frontend:
stage: build
image: node:18
script:
- cd frontend && npm ci && npm run build
artifacts:
paths:
- frontend/dist
build_images:
stage: image
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 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
deploy_prod:
stage: deploy
image: alpine:3.18
before_script:
- apk add --no-cache openssh-client
script:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh -o StrictHostKeyChecking=no $DEPLOY_USER@$DEPLOY_HOST "docker pull $CI_REGISTRY_IMAGE/backend:$CI_COMMIT_SHORT_SHA && docker pull $CI_REGISTRY_IMAGE/frontend:$CI_COMMIT_SHORT_SHA && docker-compose -f /srv/app/docker-compose.yml up -d"
only:
- main
Explications : ce pipeline utilise Docker-in-Docker (dind) pour builder et pousser des images. En production, il est possible d'utiliser une étape de déploiement SSH pour déclencher la mise à jour via docker-compose, ou d'appeler l'API Kubernetes/Helm si l'infrastructure cible est un cluster.
Bonnes pratiques de sécurité et d'opérations
- Variables protégées : protéger les variables sensibles et n'autoriser que les branches protégées à déclencher les déploiements.
- Limitation des runners : utiliser des runners dédiés et labellisés pour les jobs de build et de déploiement.
- Scan d'images : intégrer des outils de scanning (Trivy, Clair) dans le pipeline.
- Rollback : versionner les images et conserver un plan de rollback automatique.
- Monitoring : vérifier les métriques et logs post-déploiement via Prometheus/ELK.
Stratégies de déploiement
Plusieurs stratégies peuvent être adoptées selon les contraintes :
- Blue/Green : déployer une nouvelle version sur un environnement parallèle et basculer le trafic.
- Canary : répartir progressivement la charge vers la nouvelle version.
- Rolling updates : mise à jour progressive des instances pour minimiser l'impact.
Conclusion
La combinaison de Docker et GitLab CI/CD permet d'automatiser efficacement le cycle de vie des applications Full Stack. En appliquant des images multi-stage, des étapes de test rigoureuses, et une gestion sécurisée des variables, l'équipe obtient un pipeline fiable, reproductible et maintenable. L'intégration avec le registre GitLab simplifie le flux complet depuis le commit jusqu'au déploiement.
À 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