---
title: Déployer avec Docker
description: Livrer une image versionnée, vérifier sa santé et revenir en arrière.
---

Le déploiement commence après la CI. Les tests ont réussi et une image immuable a été publiée dans un registry :

```text
image testée et versionnée
          ↓
pull sur le serveur
          ↓
remplacement des conteneurs
          ↓
contrôles de santé
```

<Callout title="Construire une fois, exécuter partout" type="success">
  Le serveur ne recompile rien. Il lance exactement l'image produite et validée par la CI.
</Callout>

## Préparer le Compose de production

```yaml
services:
  backend:
    image: ghcr.io/organisation/mon-app-backend:${IMAGE_TAG:?IMAGE_TAG requis}
    restart: unless-stopped
    env_file:
      - .env.prod
    healthcheck:
      test:
        - CMD
        - node
        - -e
        - fetch('http://localhost:3000/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 20s

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
```

Le tag doit identifier une version précise, par exemple `v1.4.0` ou un SHA de commit. Évite `latest`, qui ne permet pas de savoir sans ambiguïté ce qui tourne.

## Déployer une version

Dans `/srv/mon-app`, écris le tag choisi dans `.env.release` :

```dotenv
IMAGE_TAG=v1.4.0
```

Puis récupère et lance les images :

```bash
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
```

`--no-build` empêche toute reconstruction sur le serveur. Les données vivent dans les volumes et ne sont pas supprimées par le remplacement des conteneurs.

## Vérifier immédiatement

```bash
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs --tail=100
curl --fail --show-error https://app.example.com/health
```

Un déploiement n'est réussi que lorsque :

- les conteneurs sont démarrés et en bonne santé ;
- les migrations de données ont terminé ;
- l'URL publique répond ;
- les journaux ne montrent pas de boucle d'erreurs ;
- une action métier courte fonctionne.

## Revenir à la version précédente

Un rollback réutilise l'ancien tag :

```dotenv
IMAGE_TAG=v1.3.2
```

Relance ensuite `pull` puis `up -d --no-build`. Conserve au moins quelques versions dans le registry pour rendre ce retour possible.

<Callout title="Attention aux migrations" type="warn">
  Une image peut revenir en arrière, mais une migration destructive de base de données peut être irréversible. Préfère des migrations rétrocompatibles en plusieurs étapes et sauvegarde avant les changements sensibles.
</Callout>

## Ce qui est déployé et ce qui persiste

| Élément | Comportement |
| --- | --- |
| image applicative | remplacée à chaque version |
| conteneur | recréé à partir de l'image |
| fichier Compose | versionné et copié explicitement |
| secrets | conservés hors de Git sur le serveur ou dans un coffre |
| volume de données | persiste entre les déploiements et doit être sauvegardé |
| journaux | collectés et soumis à une rotation |

## Checklist

- [ ] image versionnée disponible dans le registry ;
- [ ] sauvegarde récente et restauration déjà testée ;
- [ ] tag de la version précédente connu ;
- [ ] configuration et secrets présents sur le serveur ;
- [ ] healthchecks opérationnels ;
- [ ] déploiement sérialisé pour éviter deux mises à jour simultanées ;
- [ ] vérification fonctionnelle et rollback documentés.

La rubrique [CI/CD](/docs/ci-cd/principes) automatise maintenant ces étapes sans confondre validation, publication et mise en production.
