Ce que vous saurez faire
Au terme de ce tutoriel pratique, vous serez un développeur capable de prendre en charge la chaîne complète DevOps sans dépendre d'une équipe ops séparée, ce qui est crucial pour les startups et PME africaines où une seule personne porte plusieurs casquettes. Vous saurez versionner votre code avec Git en respectant Gitflow ou trunk-based, automatiser vos builds avec GitHub Actions ou GitLab CI, conteneuriser vos applications avec Docker, déployer sur un VPS Contabo ou OVH à 6 000 FCFA/mois avec Ansible, surveiller vos services avec Uptime Kuma et Loki, et gérer vos secrets avec Vault ou doppler. Vous maîtriserez aussi le déploiement blue-green et le rollback en moins de 60 secondes, le monitoring avec alertes WhatsApp via Twilio, et l'optimisation des coûts cloud (typiquement diviser par 3 la facture mensuelle d'un projet existant). À la fin, vous serez autonome sur un cycle complet de la commit au déploiement production en moins de 10 minutes.
Étape 1 : Maîtriser Git au-delà du commit/push
La fondation de tout DevOps. Configurez votre identité et activez les bonnes pratiques :
git config --global user.name "Aminata Sow"
git config --global user.email "aminata@boutique-dakar.sn"
git config --global pull.rebase true
git config --global init.defaultBranch main
git config --global core.autocrlf input
Apprenez les commandes vitales : git rebase -i HEAD~3 pour nettoyer l'historique, git stash pour mettre de côté, git bisect pour trouver le commit qui a cassé. Adoptez les commits conventionnels : feat:, fix:, chore:, docs:.
Étape 2 : Choisir une stratégie de branche
Pour une équipe de 1 à 3 développeurs, le trunk-based est plus simple :
main (production, toujours deployable)
|
+-- feature/paiement-wave (courte vie, < 2 jours)
+-- fix/bug-panier-vide (idem)
Pour une équipe plus grande, Gitflow avec develop, release/*, hotfix/*. Documentez votre choix dans CONTRIBUTING.md.
Étape 3 : Premier pipeline CI avec GitHub Actions
Créez .github/workflows/ci.yml dans votre projet :
name: CI
on:
push:
branches: [main, develop]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
À chaque push, GitHub teste automatiquement. Gratuit jusqu'à 2000 minutes/mois pour les projets privés.
Étape 4 : Conteneuriser avec Docker
Pour une application Node.js, créez un Dockerfile optimisé :
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json .
EXPOSE 3000
USER node
CMD ["node", "dist/index.js"]
Build et test local :
docker build -t monapp:dev .
docker run -p 3000:3000 monapp:dev
Étape 5 : Stocker les images sur un registry
Plusieurs options selon le budget :
- Docker Hub : 1 repo prive gratuit
- GitHub Container Registry : illimite si projet public
- Self-hosted : Harbor sur VPS (gratuit, plus de controle)
Push automatique depuis CI :
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/aminata/monapp:${{ github.sha }}
Étape 6 : Provisionner le VPS avec Ansible
Au lieu de configurer manuellement à chaque fois, écrivez playbook.yml :
- hosts: production
become: yes
tasks:
- name: Install Docker
shell: curl -fsSL https://get.docker.com | sh
- name: Add deploy user
user:
name: deploy
groups: docker
shell: /bin/bash
- name: Configure firewall
ufw:
rule: allow
port: "{{ item }}"
loop: [22, 80, 443]
- name: Enable fail2ban
apt:
name: fail2ban
state: present
Lancez : ansible-playbook -i inventory.yml playbook.yml. Reproductible à 100 %.
Étape 7 : Déployer avec Docker Compose
Sur le VPS, créez /opt/monapp/docker-compose.yml :
services:
app:
image: ghcr.io/aminata/monapp:latest
restart: unless-stopped
environment:
NODE_ENV: production
DATABASE_URL: ${DATABASE_URL}
labels:
- traefik.http.routers.app.rule=Host(`monapp.sn`)
- traefik.http.routers.app.tls.certresolver=letsencrypt
traefik:
image: traefik:v3.0
ports: [80:80, 443:443]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./letsencrypt:/letsencrypt
Étape 8 : Pipeline de déploiement continu (CD)
Étendez votre workflow pour déployer automatiquement après merge sur main :
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.VPS_HOST }}
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/monapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
Étape 9 : Gérer les secrets correctement
Ne JAMAIS committer un mot de passe. Trois niveaux selon la maturité :
1. Debutant : .env local + GitHub Secrets pour CI
2. Intermediaire : Doppler (gratuit jusqu'a 5 utilisateurs)
3. Avance : HashiCorp Vault self-hosted
Configuration Vault basique :
vault kv put secret/monapp/prod \
DATABASE_URL="postgres://..." \
WAVE_API_KEY="sk_live_..."
vault kv get secret/monapp/prod
Étape 10 : Monitoring et alertes
Stack légère pour PME : Uptime Kuma + Loki + Grafana :
uptime-kuma:
image: louislam/uptime-kuma
volumes:
- kuma_data:/app/data
ports: [3001:3001]
loki:
image: grafana/loki:2.9.0
volumes:
- loki_data:/loki
grafana:
image: grafana/grafana:latest
ports: [3000:3000]
Configurez des alertes WhatsApp via Twilio ou par email vers votre équipe d'astreinte.
Étape 11 : Logs centralisés avec Loki
Utilisez Promtail pour envoyer tous les logs Docker à Loki :
promtail:
image: grafana/promtail:2.9.0
volumes:
- /var/log:/var/log
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail.yml:/etc/promtail/config.yml
Dans Grafana, créez des requêtes LogQL pour chercher les erreurs : {container="app"} |= "error".
Étape 12 : Stratégie de déploiement zéro downtime
Pattern blue-green simplifié avec Traefik :
# Demarrer la nouvelle version a cote de l'ancienne
docker compose -f docker-compose.green.yml up -d
# Attendre que healthcheck passe
until curl -f http://localhost:3001/health; do sleep 2; done
# Basculer le trafic via label Traefik
# Stopper l'ancienne version
docker compose -f docker-compose.blue.yml down
Pour un rollback : il suffit d'exécuter docker compose pull image:precedent_sha && docker compose up -d.
Étape 13 : Tests d'infrastructure et de charge
Avant chaque mise en production majeure, testez la charge avec k6 :
import http from 'k6/http';
import { check } from 'k6';
export let options = { vus: 50, duration: '1m' };
export default function() {
let r = http.get('https://monapp.sn/api/products');
check(r, { 'status 200': (r) => r.status === 200 });
}
Lancez : k6 run loadtest.js. Sur un VPS 4 vCPU à 12 000 FCFA/mois, attendez-vous à tenir 200 req/s sur du Node.js bien optimisé.
Étape 14 : Documentation opérationnelle vivante
Maintenez à jour trois documents essentiels :
- README.md : comment lancer en local (npm install, npm run dev)
- DEPLOY.md : comment deployer manuellement si CI HS
- RUNBOOK.md : que faire si X plante (commandes, contacts, escalade)
Ajoutez aussi un ARCHITECTURE.md avec un diagramme (Mermaid intégré au markdown). Cela permet à un nouveau développeur de devenir productif en moins de 2 jours, contre 2 semaines sans documentation.
Erreurs
Erreur 1 : Déployer manuellement en SSH. Tôt ou tard, vous oublierez une étape. Automatisez TOUT, même pour un projet de 200 lignes.
Erreur 2 : Pas de healthcheck. Sans HEALTHCHECK dans le Dockerfile, Docker croit que le service est OK alors qu'il crash en boucle.
Erreur 3 : Ignorer les logs. "Ça marche chez moi" est l'épitaphe du DevOps. Centralisez les logs dès le jour 1.
Erreur 4 : Latest tag en production. Utilisez TOUJOURS le SHA du commit ou un tag versionné. Sinon impossible de faire un rollback fiable.
Erreur 5 : Pas de backup automatisé. Configurez un cron quotidien qui exporte la base et l'envoie sur S3 (Backblaze B2 = 4 800 FCFA pour 1 To/mois).
Erreur 6 : Surveiller seulement les serveurs. Surveillez aussi les expirations (domaine, certificat TLS, abonnement Twilio) qui causent 30 % des incidents.
Erreur 7 : Tout monter en cluster Kubernetes. Pour 90 % des PME, Docker Compose sur 1 ou 2 VPS suffit. K8s = 4 fois plus cher en heures d'administration.
Checklist
- Git configuré avec commits conventionnels
- Stratégie de branche documentée dans CONTRIBUTING.md
- Pipeline CI qui lint, teste et build
- Dockerfile multi-stage avec utilisateur non-root
- Images poussées sur un registry avec tag immutable
- VPS provisionné via Ansible (reproductible)
- UFW + fail2ban activés
- Docker Compose avec Traefik et certificats Let's Encrypt
- Pipeline CD automatique sur merge main
- Secrets gérés (jamais dans le code)
- Uptime Kuma surveillant tous les endpoints critiques
- Logs centralisés sur Loki
- Procédure de rollback testée < 60 secondes
- Backup quotidien automatisé et restauré au moins une fois