Avant de commencer
- Docker et son plugin Compose installés (voir installer Docker sur Debian ou Ubuntu)
- Les commandes de base (voir les commandes Docker essentielles)
En clair
Avec docker run, chaque conteneur se lance avec une longue ligne d'options qu'il faut retenir ou noter quelque part. Docker Compose remplace ces lignes par un fichier, compose.yaml, qui décrit toute l'application : les conteneurs, leurs ports, leurs volumes, leurs variables, et comment ils se parlent. C'est la recette écrite plutôt que de mémoire : on la relit, on la modifie, on la sauvegarde avec Git, et on relance tout en une commande.
1. Pourquoi Compose
Avec docker run |
Avec Compose |
|---|---|
| Une commande par conteneur, à retenir | Un fichier qui décrit tous les conteneurs |
| Réseau et noms à créer à la main | Un réseau privé créé automatiquement ; les services se joignent par leur nom |
| Ordre de démarrage à gérer soi-même | Dépendances déclarées (depends_on) |
| Configuration difficile à partager | Fichier texte, versionnable avec Git, relisible |
| Mise à jour conteneur par conteneur | docker compose pull puis docker compose up -d |
2. La structure du fichier
services: # les conteneurs de l'application
nom-du-service:
image: … # l'image et sa version
restart: … # la politique de redémarrage
ports: […] # les ports publiés sur l'hôte
environment: … # les variables de configuration
volumes: […] # les données persistantes
depends_on: … # les services à démarrer avant
volumes: # les volumes nommés utilisés plus haut
nom-du-volume:
networks: # facultatif : réseaux supplémentaires
Le fichier s'appelle compose.yaml (les anciens noms docker-compose.yml restent reconnus). L'indentation se fait avec des espaces, jamais des tabulations, et elle a un sens : deux espaces par niveau.
Rangez chaque application dans son propre dossier, par exemple /opt/forgejo/. Le nom du dossier devient le nom du projet, qui préfixe les conteneurs, volumes et réseaux créés.
3. Un exemple complet : Forgejo et PostgreSQL
Forgejo est une forge Git libre, auto-hébergeable, qui stocke ses données dans une base PostgreSQL. C'est un bon exemple d'application à deux services.
Le fichier des secrets : .env
sudo mkdir -p /opt/forgejo
cd /opt/forgejo
Créez /opt/forgejo/.env :
POSTGRES_PASSWORD=remplacez-par-un-mot-de-passe-long
FORGEJO_VERSION=16
Générez un mot de passe solide avec openssl rand -base64 32, puis protégez le fichier :
sudo chmod 600 /opt/forgejo/.env
Compose lit automatiquement le fichier .env placé à côté de compose.yaml et remplace les ${VARIABLE} du fichier par leur valeur.
Le fichier compose.yaml
services:
forgejo:
image: codeberg.org/forgejo/forgejo:${FORGEJO_VERSION}
container_name: forgejo
restart: unless-stopped
environment:
USER_UID: "1000"
USER_GID: "1000"
FORGEJO__database__DB_TYPE: postgres
FORGEJO__database__HOST: db:5432
FORGEJO__database__NAME: forgejo
FORGEJO__database__USER: forgejo
FORGEJO__database__PASSWD: ${POSTGRES_PASSWORD}
volumes:
- forgejo-data:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "192.168.1.10:3000:3000"
- "192.168.1.10:2222:22"
depends_on:
db:
condition: service_healthy
db:
image: postgres:17-alpine
container_name: forgejo-db
restart: unless-stopped
environment:
POSTGRES_DB: forgejo
POSTGRES_USER: forgejo
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- forgejo-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U forgejo -d forgejo"]
interval: 10s
timeout: 5s
retries: 5
volumes:
forgejo-data:
forgejo-db:
| Élément | Explication |
|---|---|
${FORGEJO_VERSION} |
La version vient du fichier .env : on la change à un seul endroit. Vérifiez la dernière version stable sur le site de Forgejo |
FORGEJO__database__HOST: db:5432 |
Forgejo joint la base par le nom du service db, dans le réseau privé créé par Compose |
Pas de ports: pour db |
La base n'est joignable que par les conteneurs du projet, jamais depuis le réseau |
ports: "192.168.1.10:3000:3000" |
L'interface web n'est publiée que sur l'adresse du réseau local (les ports publiés contournent ufw) |
2222:22 |
L'accès Git en SSH, sur le port 2222 pour ne pas entrer en conflit avec le SSH du serveur |
healthcheck et condition: service_healthy |
Forgejo attend que PostgreSQL soit réellement prêt, pas seulement démarré |
/etc/localtime:ro |
Le conteneur prend le fuseau horaire de l'hôte, en lecture seule |
volumes: en bas |
Déclare les deux volumes nommés : données Git et base de données |
Démarrer et vérifier
Vérifiez d'abord la syntaxe et le remplacement des variables :
sudo docker compose config
La commande affiche le fichier final, variables remplacées, ou une erreur précise. Puis démarrez :
sudo docker compose up -d
sudo docker compose ps
NAME IMAGE SERVICE STATUS PORTS
forgejo codeberg.org/forgejo/forgejo:16 forgejo Up 20 seconds 192.168.1.10:3000->3000/tcp, 192.168.1.10:2222->22/tcp
forgejo-db postgres:17-alpine db Up 31 seconds (healthy)
Ouvrez http://192.168.1.10:3000 et terminez l'assistant d'installation de Forgejo : les paramètres de base de données sont déjà remplis. Créez le compte administrateur (par exemple spo).
Le fichier .env ne va pas dans Git
Si vous versionnez le dossier, ajoutez .env au fichier .gitignore, et fournissez à la place un .env.exemple sans les vraies valeurs. Un mot de passe publié sur une forge, même privée, doit être considéré comme compromis.
4. Les commandes du quotidien
Toutes se lancent dans le dossier qui contient compose.yaml (ou avec -f /opt/forgejo/compose.yaml).
| Commande | Effet |
|---|---|
docker compose up -d |
Crée et démarre tous les services ; recrée ceux dont la configuration a changé |
docker compose ps |
État des services du projet |
docker compose logs -f |
Journaux de tous les services en direct |
docker compose logs -f --tail 100 forgejo |
Journaux d'un seul service |
docker compose restart forgejo |
Redémarre un service |
docker compose stop |
Arrête les services sans les supprimer |
docker compose down |
Arrête et supprime les conteneurs et le réseau ; les volumes sont conservés |
docker compose exec db psql -U forgejo |
Lance une commande dans un service en cours |
docker compose pull |
Télécharge les nouvelles versions des images |
docker compose config |
Valide le fichier et affiche le résultat final |
docker compose top |
Processus de chaque service |
docker compose down -v
L'option -v supprime aussi les volumes du projet : la base de données et les dépôts Git disparaissent. Ne l'utilisez que pour effacer volontairement un projet de test.
5. Mettre à jour
- Lisez les notes de version de l'application : une version majeure peut demander une migration.
- Sauvegardez (partie 6).
- Changez la version dans
.envsi vous suivez une version précise, puis :
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune
Compose recrée uniquement les conteneurs dont l'image a changé. Suivez les journaux (docker compose logs -f) pendant le redémarrage.
Les mises à jour automatiques
Des outils peuvent mettre à jour les conteneurs tout seuls. C'est pratique pour un service sans enjeu, mais risqué pour une base de données ou une application qui demande des migrations : une mise à jour ratée à 3 h du matin passe inaperçue jusqu'au lendemain. Préférez des mises à jour planifiées et surveillées, et fixez les versions majeures.
6. Sauvegarder
Une sauvegarde d'application Compose comprend trois éléments :
| Élément | Comment |
|---|---|
La configuration : compose.yaml et .env |
Copie du dossier /opt/forgejo/ (le .env dans un emplacement protégé) |
| La base de données | Export cohérent avec l'outil de la base |
| Les fichiers de l'application | Archive du volume, application arrêtée ou figée |
Export de la base PostgreSQL, sans arrêter le service :
sudo docker compose exec -T db pg_dump -U forgejo -d forgejo | gzip > forgejo-db-$(date +%F).sql.gz
Archive du volume de données, service arrêté pour garantir la cohérence :
sudo docker compose stop forgejo
sudo docker run --rm -v forgejo_forgejo-data:/data:ro -v "$PWD":/sauvegarde debian:13 tar czf /sauvegarde/forgejo-data-$(date +%F).tar.gz -C /data .
sudo docker compose start forgejo
Le nom réel du volume est préfixé par le nom du projet (forgejo_forgejo-data) : vérifiez-le avec docker volume ls. Copiez ensuite ces archives hors du serveur (voir la règle 3-2-1), et testez une restauration.
7. Les bonnes pratiques
| Pratique | Pourquoi |
|---|---|
Un dossier par application (/opt/nom/) avec son compose.yaml et son .env |
Organisation claire, sauvegarde simple |
Versions fixées (postgres:17-alpine, pas latest) |
Pas de changement majeur surprise |
Secrets dans .env, droits 600, hors de Git |
Les mots de passe ne traînent pas dans le fichier principal |
Bases de données sans ports: |
Elles ne sont joignables que par l'application |
| Ports publiés sur une adresse précise ou derrière un reverse proxy | Les ports publiés contournent le pare-feu de l'hôte |
restart: unless-stopped |
Redémarrage automatique après un plantage ou un redémarrage du serveur |
healthcheck sur les services critiques |
Démarrage dans le bon ordre, état visible dans docker compose ps |
docker compose config avant chaque up |
Les erreurs de syntaxe ou de variables apparaissent avant de casser le service |
Fichier versionné avec Git (sans .env) |
Historique des changements, retour arrière facile |
À retenir
compose.yamldécrit toute l'application ; les services se joignent par leur nom dans un réseau privé.- Secrets dans
.env(droits 600, jamais dans Git), versions d'images fixées. docker compose up -d,ps,logs -f,pull,down: les cinq commandes du quotidien.down -vsupprime les données : à manier avec précaution.- Sauvegarde = configuration + export de la base + volumes, copiée hors du serveur et testée.