docs: add server and CI/CD guides
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user