Découvrir la CI : Comment build mon SaaS en 3 minutes pour la prod ? 📦

· Lucas Videlaine


# 📚 Sommaire


# 1. Introduction : Une série CI/CD pour les devs pressés

Bienvenue dans cette série de deux articles dédiée à l’automatisation du cycle de vie d’un projet SaaS grâce à la CI/CD.

Que tu sois développeur freelance, étudiant, ou en train de lancer ton propre SaaS, cette série te montrera comment automatiser rapidement — et proprement — ton processus de build et de déploiement.

🎯 Objectif : à la fin de cet article, tu sauras comment :

  • builder automatiquement ton application,
  • puis la déployer en production dès que ton code est prêt.

# 🧱 Ce qu’on va faire ensemble

Dans ce premier article, on se concentre sur la CI — Continuous Integration — l’Intégration Continue :

🔧 Automatiser le build de ton application à chaque push de code.
✨ ​En bonus, on va même voir comment scanner ton code source à la recherche de vulnérabilités !

Dans le prochain article, on abordera la CD — Continuous Deployment — le Déploiement Continu :

🚀 Envoyer automatiquement ton build en production, sans manip manuelle.


# 💡 Contexte du use-case — notre fil rouge

Imaginons, tu as développé un site vitrine avec React JS pour présenter ton futur service SaaS (ou tout autre webapp, mais prenons un exemple simple et concret !)
Tu veux maintenant que chaque modification du code que tu push sur ton repository Git :

  1. soit automatiquement scannée et buildée,
  2. soit prête à être déployée sans intervention manuelle.

Nous allons utiliser une stack simple et accessible :

  • GitLab pour héberger ton code et l'image du conteneur qui sera buildé,
  • GitLab-CI pour automatiser le scan et la construction de l'iamge,
  • Docker pour packagé et alléger au maximum ton build (tu n'es pas complétement à l'aise avec Docker ? Pas de problème : un article sur les commandes de base t'attend déjà).

Pas besoin d’infrastructure complexe ni de configuration obscure : on va droit au but.


🎯 Résultat à la fin de cet article :
Un build automatisé à chaque commit, prêt à être déployé sereinement.


Parfait ! Voici la partie 2 – C’est quoi la CI ?, toujours au format Markdown, clair et pédagogique :


# 2. C’est quoi la CI ? (Intégration Continue)

L’Intégration Continue (ou Continuous Integration, CI) est une pratique clé du DevOps moderne. Elle consiste à automatiser l’exécution de tests, le build et la validation de ton code dès qu’un changement est poussé dans ton dépôt Git.

Dit autrement :

🛠️ Tu écris du code → tu pushes → ton projet est automatiquement construit et vérifié.


# ✅ Une définition simple

CI = un script qui vérifie et construit ton code à chaque commit, sans que tu aies besoin d’y penser.

Plus concrètement, une pipeline CI peut :

  • installer les dépendances de ton projet,
  • exécuter des tests unitaires ou de qualité de code,
  • compiler, builder ou packager ton app,
  • produire des fichiers prêts pour la production (par ex. un dossier dist/ ou build/).

Aujourd'hui, Docker est largement employé dans les pipelines CI. Il permet à la pipeline de construire une image de conteneur, objet léger et simple à stocker pour les étapes suivantes du cycle vie logicielle (CD, etc.).


# 🤝 La CI dans une démarche DevOps

La CI est l’un des premiers pas vers une démarche DevOps. Elle favorise :

  • la collaboration : tout le monde travaille sur une base de code testée et fonctionnelle,
  • la détection rapide des erreurs : un bug dans la branche ? Tu le sais dès le commit,
  • la réduction du temps de mise en production : pas besoin de tout refaire à la main.

🔁 La CI élimine les phases de “ça marche chez moi”, “je rebuild vite fait avant de pousser” et autres sources de friction.


# 💡 Pourquoi utiliser la CI pour mon SaaS ?

Tu pourrais penser : “Mais je suis seul sur ce projet, j’ai besoin de tout ça ?”
La réponse est : oui, surtout.

Voici pourquoi :

  • Tu gagnes du temps : pas besoin de répéter manuellement les builds à chaque changement.
  • Ton code est toujours prêt pour la prod : pas de mauvaise surprise à la dernière minute.
  • Tu fiabilises ton projet : moins de risques d’introduire un bug ou de casser quelque chose.

💬 Astuce : Tu veux t’entraîner à la CI ? Notre projet React vitrine est un excellent terrain de jeu !


Très bien, voici la partie 3 – Outils utilisés pour notre pipeline, toujours en Markdown, avec un ton pédagogique et accessible :


# 3. Outils utilisés pour notre pipeline

Pour automatiser le build de notre site React, on va s’appuyer sur des outils modernes, simples à prendre en main, et largement utilisés dans l’écosystème Dev et DevOps.


# 🗂️ Git – La base de ton projet

Si tu lis cet article, tu utilises très probablement Git pour versionner ton code.
La CI va justement s’appuyer sur ton dépôt Git pour savoir quoi builder, quand et comment.

Chaque fois que tu fais un commit et que tu le pushes, Git déclenche une nouvelle version du code à analyser. C’est là que la magie de la CI entre en jeu.


# 🦊 GitLab – Le hub de ton projet

Dans cette série, nous allons utiliser GitLab, un service de gestion de code source qui inclut nativement un système CI/CD intégré (contrairement à GitHub qui nécessite des actions externes, ou des outils comme GitHub Actions ou CircleCI).

Pourquoi GitLab ?

  • Pas besoin d’installer ou connecter un outil externe,
  • La CI/CD est native, simple et efficace,
  • Tu peux héberger ton dépôt en cloud (gitlab.com) ou on-premise (GitLab CE).

# 🔁 GitLab-CI – Le moteur du pipeline

GitLab-CI est le moteur qui exécute ton pipeline. Il lit un fichier de configuration .gitlab-ci.yml placé à la racine de ton projet, et déclenche automatiquement les étapes que tu y définis (scan, build, test, déploiement, etc.).

Ce fichier te permet de dire à GitLab :

  • quelles étapes à réaliser,
  • quelles commandes exécuter,
  • quoi garder comme résultat (les artifacts),
  • dans quels cas exécuter chaque étape (branches, conditions, etc.).

📁 Un seul fichier .gitlab-ci.yml = toute la logique de ton pipeline.


# ⚠️ Prérequis : Ton projet doit être hébergé sur GitLab.com

Pour suivre les exemples de cette série :

  • crée un compte gratuitement sur gitlab.com,
  • pousse ton dépôt (React) sur un nouveau projet (public ou privé, comme tu préfères),
  • assure-toi que ton fichier .gitlab-ci.yml est bien à la racine du dépôt.

💬 Astuce : Tu peux tester ton fichier .gitlab-ci.yml dans l’UI GitLab avant même de le pusher, via l’outil CI Lint.


# 4. Docker : l’allié discret de tout bon SaaS

Pour que ta pipeline CI fonctionne de manière fiable, reproductible, et indépendante de l’environnement de la machine qui l’exécute, on utilise Docker.

Même si ce n’est pas un article dédié à Docker, il est important de comprendre son rôle dans la CI, car GitLab-CI repose fortement dessus.


# 🛠️ Quel rapport avec la CI ?

Dans un pipeline GitLab-CI, chaque job s’exécute dans un conteneur Docker.
Tu peux choisir l’image Docker à utiliser pour ton projet en fonction de ta stack, mais dans notre cas nous allons utiliser une image générique afin de s'adapter à tous les scénarios possibles.

Pour cela, on utilise par exemple l’image docker permettant de faire du Docker-in-Docker "dind" :

image: docker:24.0.2-dind

Cela signifie : "GitLab, pour ce job, utilise telle image Docker dans telle version". Pour toutes les images et leurs versions (qu'on appelle "tag"), je t'invite à te rendre sur Docker Hub.


# 📦 Le Dockerfile

Tu peux ensuite créer ton propre Dockerfile pour décrire les besoins de ton app.
Pour un projet React standard, voici une base que tu peux utiliser et ajuster selon tes envies :

Dockerfile :

# Dockerfile

FROM node:alpine3.22 AS build

WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm install

# Copy project files
COPY . .

# Build the application
RUN npm run build

# Production stage
FROM nginx:alpine

# Copy built assets from build stage
COPY --from=build /app/_site /usr/share/nginx/html

# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Expose port 80
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Le fichier nginx.conf :

# nginx.conf
server {
listen 80;
server_name localhost;

root /usr/share/nginx/html;
index index.html;

# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Cache static assets
location /static/ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
}

Pour tester ton Dockerfile, rien de plus simple :

docker build --tag 'mon-saas:1.0' ./Dockerfile
docker run --detach -p 8080:80 'mon-saas:1.0'
curl localhost:8080


# 💬 En résumé

Docker permet à GitLab CI de builder ton projet dans un environnement propre, contrôlé et réutilisable.
Tu n’as rien à installer sur ta machine : tout est exécuté dans le cloud, à chaque commit. Pour autant je t'encourage vivement à l'utiliser aussi localement afin de tester ton app dans conteneur est assurer son fonctionnement agnostic !


# 5. Une pipeline CI "plug & play"

Maintenant que tu comprends les bases de la CI et le rôle de Docker, passons à la mise en pratique.
L’objectif : te fournir un pipeline clé en main que tu peux coller dans ton dépôt GitLab pour builder automatiquement ton SaaS à chaque push.


# ⚙️ Un fichier .gitlab-ci.yml simple et efficace

Voici un pipeline CI complet, prêt à l’emploi, intégrant les bonnes pratiques DevSecOps dès le départ, et qui s'adaptera à tous tes projets :

# .gitlab-ci.yml

image: docker:24.0.2-dind

services:
- name: docker:dind
entrypoint: ['env', '-u', 'DOCKER_HOST']
command: ['dockerd-entrypoint.sh']

variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
REGISTRY: $CI_REGISTRY
REPOSITORY: $CI_PROJECT_NAMESPACE
IMAGE_NAME: $CI_PROJECT_NAME
IMAGE_TAG: latest

include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/SAST-IaC.latest.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Jobs/Container-Scanning.gitlab-ci.yml

stages:
- test
- build
- scan

sast:
stage: test

build:
stage: build
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
script:
- docker build -t $REGISTRY/$REPOSITORY/$IMAGE_NAME:$IMAGE_TAG .
- docker push $REGISTRY/$REPOSITORY/$IMAGE_NAME:$IMAGE_TAG
after_script:
- docker logout $REGISTRY

container_scanning:
stage: scan
variables:
CS_IMAGE: $REGISTRY/$REPOSITORY/$IMAGE_NAME:$IMAGE_TAG

# 🧠 Déchiffrons ce pipeline

ÉlémentRôle
image: docker:24.0.2-dindUtilise Docker-in-Docker pour permettre de builder et pousser une image Docker
services: docker:dindLance un démon Docker pour exécuter des builds dans le conteneur
variables:Déclare les variables d’environnement liées au registre d’images GitLab
include:Intègre des templates de sécurité fournis par GitLab (SAST, IaC, secrets, scan d’image)
stages:Définit les étapes du pipeline : test, build, scan
sast:Active les tests SAST (analyse de code statique)
build:Build et push l’image Docker de ton projet
container_scanning:Lance une analyse de sécurité sur l’image buildée

# 🔐 Ce pipeline fait bien plus que builder

Ce fichier .gitlab-ci.yml te donne un pipeline DevSecOps complet dès le départ :

  • 📦 Il build ton projet dans une image Docker
  • 🚀 Il push cette image dans le registre GitLab
  • 🛡️ Il scanne ton code source, tes secrets, ton infra-as-code et ton image Docker
  • 🔒 Il te signale toute vulnérabilité potentielle avant même que tu déploies

Pas besoin d’installer quoi que ce soit : GitLab fournit tous les outils intégrés. Tu n’as qu’à pousser ton .gitlab-ci.yml.


# 🎯 Résultat

À chaque push :

  1. Ton code est scanné pour détecter des vulnérabilités ou fuites de secrets.
  2. Ton image Docker est construite et envoyée dans le registre GitLab.
  3. Ton image est scannée pour vérifier qu’elle est propre et sûre.

Ton build est propre, sécurisé et prêt à être déployé (spoiler : c’est pour le prochain article 😉).


# 6. Tester et adapter le pipeline

Tu as ton fichier .gitlab-ci.yml prêt ? Parfait. Voyons où le placer, comment lancer ton premier pipeline, et surtout comment vérifier que tout fonctionne correctement, étape par étape.


# 📁 Où placer les fichiers dans ton dépôt ?

Voici une arborescence typique d’un projet React prêt pour la CI :

mon-saas-vitrine/
├── public/
├── src/
├── .gitignore
├── Dockerfile
├── package.json
├── package-lock.json
├── README.md
├── .gitlab-ci.yml      👈 à la racine du projet

✅ Le fichier .gitlab-ci.yml doit être à la racine du dépôt GitLab pour être détecté automatiquement.

📦 N’oublie pas ton Dockerfile à la racine aussi, sinon ça ne fonctionnera pas !


# 🚀 Pousser ton code et déclencher le pipeline

Une fois ton projet sur GitLab :

git add .
git commit -m "Ajout du pipeline CI + Dockerfile"
git push origin main

GitLab va automatiquement détecter le fichier .gitlab-ci.yml et déclencher le pipeline.

Pipelines menu on GitLab repo

Pipeline result status

Pipeline result status

On peut confirmer ainsi que les 3 étapes de notre pipeline ont été réalisées avec succès !


# 🔍 Vérifier l’exécution de chaque étape

# ✅ 1. Étape test (sast, secret-detection et IaC)

Ces étapes scannent :

  • Ton code source JS/TS pour détecter les vulnérabilités connues (XSS, injections, etc.)
  • Les fichiers versionnés pour repérer des secrets accidentellement committés (tokens, clés privées, etc.)
  • Les fichiers Infrastructure as Code (ex : Dockerfile)

Les rapports détaillés des scans sont visibles en téléchargeant les "artefacts" dans l’interface "Jobs" :

Pipeline jobs

⚠️ Point d'attention ici, ce n'est pas parce que les étapes sont "Passed" que tout est OK pour autant !

ℹ️​​ Si tu prends le temps de télécharger et parcourir les rapports de vulnérabilités, tu te rendras compte que tu peux largement améliorer la sécurité de ton app.

❇️​ Cette pipeline est dédiée pour des SaaS au stade MVP, donc je n'ai pas souhaité la rendre trop bloquante, même si des vulnérabilités sont détéctées, le build s'effectura.


# ✅ 2. Étape build

  • Cette étape build une image Docker avec ton application
  • Puis elle la push dans le registre de ton projet GitLab

Pipeline jobs

💬 Astuce : Si tu veux inspecter l’image, tu peux la pull en local :

docker login registry.gitlab.com
docker pull registry.gitlab.com/namespace/projet/image:latest

# ✅ 3. Étape container_scanning

  • Analyse l’image Docker générée : OS, librairies, dépendances
  • Rapporte les CVE critiques ou connues

Même méthode que pour le sast, secret-detection et IaC : dans Build/Jobs tu retrouveras le rapport de scan complet de l'image nouvellement construite. A toi de prendre le temps de la lire, de la comprendre, et de corriger ce que tu juges important pour ton SaaS !


# ⚠️ Si le pipeline échoue

🧩 GitLab t’indique clairement quelle étape a échoué, et pourquoi.

  • Clique sur le nom du job concerné dans l’UI du pipeline
  • Inspecte les logs complets pour corriger le problème

💡 Astuce : Active les "failures notifications" dans les paramètres pour être alerté par e-mail ou via intégration Slack.


# 7. Conclusion : ton build est prêt !

Félicitations ! 🎉 Tu viens de mettre en place un pipeline CI complet, sécurisé et automatisé pour ton projet SaaS.
En quelques minutes, tu as posé les bases d’un cycle de développement professionnel, fiable et prêt pour la production.


# ✅ Ce que tu as accompli

  • Compris les fondamentaux de la CI et son rôle dans une démarche DevOps
  • Utilisé GitLab-CI pour automatiser ton processus de build
  • Intégré Docker pour fiabiliser ton environnement d’exécution
  • Ajouté des scans de sécurité (SAST, secrets, container scanning) sans effort
  • Préparé ton projet pour le déploiement continu

# 🚧 Ce qu’il reste à faire ? Le déploiement !

Ton build est prêt, propre, versionné…
Il ne reste plus qu’à l’envoyer en production.

Et ça tombe bien : c’est l’objet du prochain article de cette série 👇


# 🔜 [À venir] Partie 2 – Découvrir la CD : Comment déployer mon build en prod en 3 minutes ?

Tu y apprendras à :

  • Déployer ton image Docker automatiquement sur un VPS
  • Mettre en place et configurer un modern reverse proxy
  • Automatiser les redéploiements avec Docker Compose

📌 En résumé : tu viens de franchir une étape clé dans l’industrialisation de ton projet.
Même en solo, tu utilises les mêmes outils que dans les grandes équipes.


Merci pour ta lecture 🙌
N’hésite pas à partager cet article ou me faire part de tes retours, idées d'amélioration ou suggestions d’articles !