Articlepar DevBlog

Un pipeline CI/CD avec GitHub Actions et Docker

Construire un pipeline simple et efficace : une seule étape de vérification, un Dockerfile multi-étapes et un cache bien placé.

  • #ci
  • #docker
  • #github-actions
  • #devops

L'objectif

À chaque push, la CI doit répondre à une seule question : ce code peut-il être livré ? Le plus simple est de réutiliser la commande que vous lancez en local.

Un workflow minimal

yaml
name: CI

on:
  push:
  pull_request:

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm run check

npm run check enchaîne lint, vérification des types et tests. Une seule commande, identique en local et en CI : pas de dérive entre les deux.

Dockerfile multi-étapes

Une image de production ne doit contenir ni les outils de build ni les dépendances de développement.

dockerfile
FROM node:24-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:24-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/.next ./.next
COPY --from=build /app/public ./public
COPY --from=build /app/content ./content
COPY --from=build /app/package*.json ./
RUN npm ci --omit=dev
USER node
EXPOSE 3000
CMD ["npm", "run", "start"]

Trois étapes : dépendances, build, exécution. Seule la dernière est livrée.

Optimiser le cache

L'ordre des instructions compte. Copiez d'abord package*.json et installez : tant que les dépendances ne changent pas, Docker réutilise la couche en cache, même si le code change.

Bonnes pratiques

  • USER node : ne pas exécuter en root.
  • Un fichier .dockerignore pour exclure node_modules, .git et .env.
  • Des images de base épinglées sur une version précise.
  • Ne jamais copier de secrets dans l'image.

Pour aller plus loin

Une fois la vérification en place, on peut ajouter un job de construction d'image, puis de déploiement, déclenchés uniquement sur la branche principale.

À retenir

  • Une commande de vérification unique, partagée entre local et CI.
  • Multi-stage + ordre des couches = images petites et builds rapides.
  • La CI est un contrat : ce qui passe est livrable.