Aller au contenu principal

CI/CD & déploiement Docker

Chaîne test → containerize → deploy sous GitLab CI, alignée sur le modèle maison (CRM staff_and_companiesms) : registre GitLab Container Registry, déploiement Ansible sur un hôte Docker, exposition via Traefik. Pour les builds locaux, voir Déploiement.

Vue d'ensemble

push / MR ─► test:api ─► package:image:{api,web,docs} ─► GitLab Registry ─► deploy:int:ansible
ImageSourceContenuPort
apiDockerfile.apiNestJS + Prisma (Debian)3000 (interne)
webDockerfile.webnginx : 4 SPA origine unique + proxy /api, /uploads80
docsDockerfile.docsDocusaurus statique80

Images : $CI_REGISTRY_IMAGE/{api,web,docs}:<tag> (GitLab Container Registry) où le tag vaut $CI_COMMIT_TAG sinon $CI_COMMIT_REF_SLUG (ex. develop). Les SPA sont buildées avec VITE_API_URL=/api/v1 (relatif) → bundle portable.

Dépendances / prérequis

Sur le serveur cible (intégration : jenkins@192.168.17.71:9257)

  • Docker Engine ≥ 24 + Docker Compose v2, accès au GitLab Container Registry.
  • Utilisateur SSH jenkins (clé publique installée), ~/.profile chargeant le PATH Docker.
  • Réseau Docker externe ingress (Traefik) déjà présent : docker network create ingress si absent.
  • Traefik en frontal terminant le TLS (certresolver id2realnet).
  • Un PostgreSQL externe accessible (la stack ne contient pas de service Postgres).
  • Répertoire de déploiement /docker-apps/e-learning (créé par le playbook).

Runtime des images

  • api : Node 20 (Debian), client Prisma + engine + CLI inclus. Volume ./uploads.
  • web / docs : nginx:alpine, statique.

Variables CI/CD à créer

Dans Settings → CI/CD → Variables du projet GitLab :

VariableTypeUsage
SSHKEY_CIFileclé privée SSH du compte de déploiement jenkins
INTEGRATION_ENVFilecontenu du .env d'intégration (secrets : DATABASE_URL, JWT_SECRET…). Voir ansible/environments/integration_env.example pour les clés attendues.

Le registre utilise les variables GitLab intégrées (CI_REGISTRY, CI_REGISTRY_USER, CI_JOB_TOKEN, CI_REGISTRY_IMAGE) — rien à créer. L'hôte, le port (9257), l'utilisateur et le compose_dir sont définis dans ansible/inventory.yaml (pas en variables CI).

Pull côté serveur

  • Déploiement CI : le playbook fait un docker login sur l'hôte cible avec les variables CI (CI_REGISTRY / CI_REGISTRY_USER / CI_JOB_TOKEN, valide pendant le job) avant docker compose pull. Aucun deploy token persistant requis.
  • Intervention manuelle : CI_JOB_TOKEN étant absent, la tâche de login est sautée (when: reg_token | length > 0) — c'est à l'opérateur de faire son propre docker login au registre avant de lancer le playbook ou docker compose.

Structure de déploiement (Ansible)

ansible/
├── inventory.yaml # hôtes par environnement (integration)
├── deployment_playbook.yaml # down → copie compose+.env → pull → up -d
├── docker-compose.integration.yaml # stack déployée (api+web+docs, Traefik, réseau ingress)
└── environments/
└── integration_env.example # modèle des clés ; le vrai fichier vient de la variable File INTEGRATION_ENV

Le job deploy:int:ansible matérialise d'abord environments/integration_env à partir de la variable File INTEGRATION_ENV (hors dépôt). Le playbook dépose ensuite docker-compose.integration.yamlcompose.yaml et environments/integration_env.env dans /docker-apps/e-learning, puis docker compose pull && up -d --force-recreate. Les images sont interpolées depuis le .env : image: ${REGISTRY_IMAGE}/<svc>:${TAG}. Le job deploy:int:ansible y injecte REGISTRY_IMAGE=$CI_REGISTRY_IMAGE et TAG=${CI_COMMIT_TAG:-CI_COMMIT_REF_SLUG} avant qu'Ansible ne copie le fichier.

Déclencheurs par branche

Branche / événementtestcontainerizedeploy
Merge request
developintégration (auto)
master— (images buildées, pas de cible prod définie)
tag git

Première mise en place

  1. Variable SSHKEY_CI (File) : clé privée SSH jenkins (le registre utilise les variables GitLab intégrées).
  2. Variable INTEGRATION_ENV (File) : coller le contenu du .env d'intégration (clés de integration_env.example), avec le DATABASE_URL réel (Postgres externe) et un JWT_SECRET unique :
    openssl rand -base64 48
  3. Domaines Traefik : ajuster les Host(...) dans docker-compose.integration.yaml (e-learn-st.id2real.net pour le web, docs.e-learn-st.id2real.net pour la doc).
  4. Réseau ingress présent sur l'hôte (docker network ls).
  5. Pousser sur develop → le pipeline build les 3 images puis deploy:int:ansible déploie. Les migrations Prisma s'appliquent au boot (RUN_MIGRATIONS=trueprisma migrate deploy).

Rollback

Le playbook sauvegarde l'ancien compose (compose.yaml.backup). Pour revenir à une image précédente, déployer un tag connu-bon (re-pousser le commit, ou figer un tag d'image dans le compose) puis relancer le pipeline / docker compose up -d.

Voir aussi