Aller au contenu principal
Automatisation 18 février 2026 10 min de lecture

Tutoriel : Mettre en place CI/CD avec GitHub Actions et Docker pour PME

Apprenez à automatiser vos déploiements avec GitHub Actions et Docker. Guide pratique avec pipeline CI/CD complet et économique pour PME.

M
Mohamed Boukri

Introduction : Pourquoi le CI/CD est essentiel pour votre PME

Le CI/CD (Continuous Integration/Continuous Deployment) permet d’automatiser les tests et les déploiements de vos applications. Pour une PME, ça signifie moins d’erreurs humaines, des mises en production plus rapides et une équipe qui peut se concentrer sur le développement plutôt que sur les tâches répétitives.

GitHub Actions et Docker forment le duo parfait pour les équipes IT réduites : GitHub Actions offre 2000 minutes gratuites par mois pour les repositories privés, et Docker garantit que votre application tourne de la même façon partout.

Ce tutoriel s’adresse aux développeurs, CTO et responsables techniques de PME qui veulent industrialiser leurs déploiements sans investir dans des outils complexes. On va construire ensemble un pipeline complet qui teste, build et déploie automatiquement votre application à chaque push sur la branche principale.

Key Takeaway
Avec GitHub Actions et Docker, vous pouvez mettre en place un pipeline CI/CD professionnel gratuitement jusqu’à 2000 minutes de build par mois.

Prérequis techniques et configuration initiale

Avant de commencer, assurez-vous d’avoir :

  • Un compte GitHub avec un repository contenant votre code source
  • Docker et Docker Compose installés sur votre machine locale
  • Des connaissances de base en Git et ligne de commande
  • Un serveur de déploiement accessible en SSH (VPS OVH, Coolify, ou autre)
Si vous n’avez pas encore de serveur, Coolify offre une solution d’auto-hébergement simple qui s’intègre parfaitement avec Docker.

Étape 1 : Dockeriser votre application

La première étape consiste à créer un Dockerfile optimisé. Voici un exemple pour une application Node.js avec multi-stage build :

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/index.js"]

Le multi-stage build réduit la taille finale de l’image en ne gardant que les fichiers nécessaires à l’exécution. Ici, on passe de ~1.2GB à ~150MB.

Créez ensuite un fichier docker-compose.yml pour l’environnement local :

version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=${DATABASE_URL}
- API_KEY=${API_KEY}
volumes:
- ./logs:/app/logs
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:

Testez votre configuration localement :

Terminal window
docker-compose up --build
Ne stockez jamais vos secrets directement dans les fichiers Docker. Utilisez des variables d’environnement ou un fichier .env (à ajouter dans .gitignore).

Pour les variables d’environnement, créez un fichier .env.example avec des valeurs fictives que vous commiterez, et un .env local ignoré par Git.

Étape 2 : Créer votre premier workflow GitHub Actions

GitHub Actions utilise des fichiers YAML dans le dossier .github/workflows. Créez le fichier .github/workflows/deploy.yml :

name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=sha,prefix={{branch}}-
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

Ce workflow se déclenche sur trois événements :

  • Push sur la branche main
  • Pull request vers main
  • Déclenchement manuel via l’interface GitHub

Le job build utilise GitHub Container Registry (gratuit et intégré) pour stocker vos images Docker. Le tag inclut le SHA du commit pour tracer chaque version.

Le workflow_dispatch permet de déclencher manuellement le pipeline depuis l’onglet Actions de GitHub, pratique pour les déploiements exceptionnels.

Étape 3 : Automatiser les tests et la construction de l’image Docker

Ajoutons un job de tests avant le build. Modifiez votre workflow :

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Check build
run: npm run build
build:
needs: test
runs-on: ubuntu-latest
# ... reste du job build

Le needs: test garantit que le build ne se lance que si les tests passent. La mise en cache npm (cache: 'npm') accélère les installations.

Pour les tags Docker dynamiques, la configuration docker/metadata-action génère automatiquement :

  • main-abc1234 pour un commit sur main
  • pr-42 pour une pull request

Le système de cache GitHub Actions (cache-from/cache-to: type=gha) réutilise les layers Docker entre les builds. Sur un projet moyen, ça réduit le temps de build de 5 minutes à 1 minute.

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
Le mode=max du cache stocke tous les layers intermédiaires, pas seulement le résultat final. C’est plus gourmand en stockage mais beaucoup plus rapide.

En cas d’échec, GitHub Actions envoie automatiquement une notification par email. Vous pouvez aussi configurer Slack :

- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Étape 4 : Déployer automatiquement sur votre serveur

Pour le déploiement, on ajoute un job qui se connecte en SSH au serveur et redémarre les conteneurs. Ajoutez d’abord ces secrets dans les paramètres GitHub (Settings > Secrets and variables > Actions) :

  • SSH_HOST : IP ou domaine de votre serveur
  • SSH_USER : utilisateur SSH (généralement root ou deploy)
  • SSH_KEY : clé privée SSH (générez-la avec ssh-keygen -t ed25519)

Voici le job de déploiement :

deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: Deploy to production
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /opt/app
# Login to GitHub Container Registry
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
# Pull latest image
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-${{ github.sha }}
# Update docker-compose to use new image
export IMAGE_TAG=main-${{ github.sha }}
# Zero-downtime deployment
docker-compose up -d --no-deps --build app
# Cleanup old images
docker image prune -af --filter "until=72h"

Cette approche garantit un déploiement sans interruption : Docker Compose démarre le nouveau conteneur avant d’arrêter l’ancien.

Pour un rollback automatique en cas d’échec, ajoutez un healthcheck :

script: |
cd /opt/app
# Save current version
CURRENT_VERSION=$(docker-compose images -q app)
# Deploy new version
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main-${{ github.sha }}
export IMAGE_TAG=main-${{ github.sha }}
docker-compose up -d --no-deps app
# Wait and check health
sleep 10
if ! curl -f http://localhost:3000/health; then
echo "Health check failed, rolling back..."
docker tag $CURRENT_VERSION app:latest
docker-compose up -d --no-deps app
exit 1
fi
echo "Deployment successful"
Assurez-vous que votre application expose un endpoint /health qui retourne un statut 200 quand tout fonctionne correctement.

Sur le serveur, créez un fichier docker-compose.prod.yml :

version: '3.8'
services:
app:
image: ghcr.io/votre-org/votre-app:${IMAGE_TAG}
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3

Conclusion et optimisations avancées

Vous avez maintenant un pipeline CI/CD complet qui teste, build et déploie automatiquement votre application. À chaque push sur main, GitHub Actions :

  1. Exécute les tests et le linting
  2. Build l’image Docker avec un tag unique
  3. Push l’image vers GitHub Container Registry
  4. Se connecte au serveur et déploie la nouvelle version
  5. Vérifie la santé de l’application

Les coûts sont maîtrisés : GitHub Actions offre 2000 minutes gratuites par mois pour les repositories privés (illimité pour le public). Pour une PME avec 20 déploiements par mois à 3 minutes chacun, vous restez largement dans la limite gratuite.

Dans un prochain article, on verra comment ajouter du monitoring avec Prometheus et Grafana, centraliser les logs avec Loki, et gérer des déploiements multi-environnements (staging, production) avec des workflows réutilisables.

Ressources complémentaires :

Besoin d’aide pour mettre en place votre pipeline CI/CD ? Chez Kodixar, j’accompagne les PME dans l’automatisation de leurs déploiements et la mise en place de bonnes pratiques DevOps.

Articles similaires

Disponible pour de nouveaux projets

Besoin d'aide sur ce sujet ?

Contactez-nous pour discuter de votre projet et voir comment nous pouvons vous aider.

Devis gratuit
Sans engagement
Réponse sous 24h