docs: add server and CI/CD guides
CI / 🔍 Lint & Type Check (push) Successful in 1m37s
CI / 🐳 Build & Push Image (push) Successful in 43s

This commit is contained in:
2026-07-19 21:09:08 +02:00
parent c8a75cb64a
commit fb3d3b5443
13 changed files with 761 additions and 73 deletions
+131
View File
@@ -0,0 +1,131 @@
---
title: Déploiement continu
description: Publier une image puis déployer une version par clé SSH.
---
Le workflow de livraison s'exécute après la CI, idéalement sur un tag de version. Il publie d'abord l'image, puis déclenche une opération étroite et contrôlée sur le serveur.
## Préparer une commande de déploiement côté serveur
Le serveur peut exposer un script `/usr/local/sbin/deploy-app`, appartenant à `root`, qui n'accepte qu'un tag SemVer :
```bash
#!/usr/bin/env bash
set -Eeuo pipefail
tag="${1:-}"
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Tag invalide" >&2
exit 2
fi
cd /srv/mon-app
printf 'IMAGE_TAG=%s\n' "$tag" > .env.release
docker compose --env-file .env.release -f docker-compose.prod.yml pull
docker compose --env-file .env.release -f docker-compose.prod.yml \
up -d --no-build --remove-orphans
docker compose --env-file .env.release -f docker-compose.prod.yml ps
```
Configure ensuite, avec `visudo`, une règle limitée à ce script pour le compte technique. Le workflow n'a ainsi pas besoin d'un accès Docker général ni d'un mot de passe SSH.
## Publier dans GHCR
```yaml
name: Release
on:
push:
tags: ["v*.*.*"]
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v6
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}-backend
tags: type=ref,event=tag
- uses: docker/build-push-action@v6
with:
context: ./backend
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
```
GitHub recommande d'épingler les actions à un SHA de commit pour une chaîne d'approvisionnement plus stricte. Les tags majeurs ci-dessus gardent l'exemple lisible ; remplace-les par les SHA validés par ton équipe en production.
## Déployer avec une clé
Ajoute un second job au même workflow :
```yaml
deploy:
runs-on: ubuntu-latest
needs: publish
permissions:
contents: read
environment:
name: production
url: https://app.example.com
concurrency:
group: production
cancel-in-progress: false
steps:
- name: Préparer SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.PRODUCTION_SSH_PRIVATE_KEY }}
SSH_KNOWN_HOSTS: ${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}
run: |
install -m 700 -d ~/.ssh
printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- name: Déployer la version
env:
DEPLOY_HOST: ${{ vars.PRODUCTION_HOST }}
DEPLOY_USER: ${{ vars.PRODUCTION_USER }}
IMAGE_TAG: ${{ github.ref_name }}
run: |
[[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
ssh "$DEPLOY_USER@$DEPLOY_HOST" \
"sudo /usr/local/sbin/deploy-app $IMAGE_TAG"
```
## Secrets et variables attendus
| Nom | Type | Contenu |
| --- | --- | --- |
| `PRODUCTION_SSH_PRIVATE_KEY` | secret d'environnement | clé privée dédiée au déploiement |
| `PRODUCTION_SSH_KNOWN_HOSTS` | secret d'environnement | empreinte SSH vérifiée du serveur |
| `PRODUCTION_HOST` | variable d'environnement | nom DNS ou adresse du serveur |
| `PRODUCTION_USER` | variable d'environnement | compte technique autorisé |
La clé doit être dédiée, révocable et limitée à la production. Stocke-la dans l'environnement GitHub `production`, qui peut aussi exiger une approbation et limiter les tags autorisés.
<Callout title="Pas de mot de passe SSH dans la CI" type="warn">
Utilise une clé dédiée et vérifie l'empreinte de l'hôte. Ne remplace pas `known_hosts` par un `ssh-keyscan` aveugle au moment du déploiement.
</Callout>
Pour aller plus loin : [publier des images Docker](https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images) et [protéger les environnements](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments).