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

> Découvrez la CI avec GitLab : build automatisé de votre SaaS en 3 min. Un guide clair pour débutants en DevOps, Git, Docker et GitLab-CI.

- Auteur / Author: Lucas Videlaine, Consultant & Auditeur Sécurité
- URL: https://www.videlaine.fr/posts/discover-continuous-integration/
- Langue / Language: fr
- Publié / Published: 2025-07-29
- Tags: cloud, tech, docker, gitlab

## 📚 Sommaire

- [1. Introduction : Une série CI/CD pour les devs pressés](#1.-introduction-%3A-une-série-ci%2Fcd-pour-les-devs-pressés)
- [2. C’est quoi la CI ? (*Intégration Continue*)](#2.-c’est-quoi-la-ci-%3F-(intégration-continue))
- [3. Outils utilisés pour notre pipeline](#3.-outils-utilisés-pour-notre-pipeline)
- [4. Docker : l’allié discret de tout bon SaaS](#4.-docker-%3A-l’allié-discret-de-tout-bon-saas)
- [5. Un pipeline CI "plug & play"](#5.-une-pipeline-ci-"plug-%26-play")
- [6. Tester et adapter le pipeline](#6.-tester-et-adapter-le-pipeline)
- [7. Conclusion : ton build est prêt !](#7.-conclusion-%3A-ton-build-est-prêt-!)

---

## 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**](https://www.videlaine.fr/posts/discover-continuous-deployment/), 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à**](https://www.videlaine.fr/posts/memo-docker-commands/)).

> ✅ **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](https://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](https://gitlab.com/-/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" :

```yaml
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](https://hub.docker.com/).

---

### 📦 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** :

```yml
# 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__ :

```yml
# 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 :

```yaml
# .gitlab-ci.yml

image: docker:29

services:
  - name: docker:29-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

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:
  - IMAGE_NAME="${IMAGE_NAME//./}"
  - >
      if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
        IMAGE_TAG="$CI_COMMIT_SHORT_SHA"
      else
        IMAGE_TAG="$CI_COMMIT_SHORT_SHA-dev"
      fi
  - 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
  before_script:
  - IMAGE_NAME="${IMAGE_NAME//./}"
  - >
      if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
        IMAGE_TAG="$CI_COMMIT_SHORT_SHA$"
      else
        IMAGE_TAG="$CI_COMMIT_SHORT_SHA-dev"
      fi
  - export CS_IMAGE="$REGISTRY/$REPOSITORY/$IMAGE_NAME:$IMAGE_TAG"  
```

---

### 🧠 Déchiffrons ce pipeline

| Élément                     | Rôle                                                                                    |
| --------------------------- | --------------------------------------------------------------------------------------- |
| `image: docker:29`          | Utilise Docker pour permettre de builder et pousser une image de conteneur              |
| `services: docker:29-dind`  | Lance un démon Docker-in-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 :

```bash
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](https://www.videlaine.fr/assets/img/discover-continuous-integration/01_pipelines_path.png)

![Pipeline result status](https://www.videlaine.fr/assets/img/discover-continuous-integration/02_pipeline_status.png)

![Pipeline result status](https://www.videlaine.fr/assets/img/discover-continuous-integration/03_pipeline_status.png)

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](https://www.videlaine.fr/assets/img/discover-continuous-integration/04_pipeline_jobs.png)

> ⚠️ 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](https://www.videlaine.fr/assets/img/discover-continuous-integration/05_container_registry.png)

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

```bash
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 !
