Exécuter Docker Compose en tant que service Linux avec systemd
Lancement de Docker Compose au démarrage, géré par systemd.
Docker Compose sur un serveur Linux doit démarrer au boot, s’arrêter proprement à l’extinction et survivre aux redémarrages sans intervention manuelle.
Docker Compose n’est pas Kubernetes, et c’est acceptable pour les charges de travail que ce guide cible. Pour de nombreux systèmes réels, un projet Compose sur un hôte Linux unique constitue la juste dose d’infrastructure : simple, lisible, facile à sauvegarder et suffisamment performant pour les outils internes, les projets annexes, les services auto-hébergés, les environnements de préproduction, les petites applications de production et l’infrastructure de développement.

L’éléman tmanquant est généralement la gestion des services. Exécuter cela manuellement ne suffit pas :
docker compose up -d
Une seule commande démarre la pile, mais elle ne documente pas comment la pile doit démarrer au boot, s’arrêter pendant l’extinction, recharger après des changements, écrire les journaux, récupérer après des échecs ou être mise à jour en toute sécurité. C’est là que systemd intervient.
Ce guide explique comment exécuter un projet Docker Compose en tant que service Linux avec systemd — fichiers unit, ordre de démarrage, mises à jour, journaux et sauvegardes. La répartition des responsabilités est volontaire : Docker exécute les conteneurs, Compose définit la pile, et systemd démarre et arrête le projet sur l’hôte. Cela fait partie de Outils pour développeurs - Un guide des flux de travail de développement.
Quand il est logique d’utiliser Docker Compose en tant que service
Exécuter Compose sous systemd a du sens lorsque vous avez :
- Un serveur Linux unique
- Une petite application auto-hébergée
- Une pile de proxy inverse
- Une pile de surveillance
- Une plateforme de développement locale
- Un outil interne
- Un environnement de préproduction
- Un service de production simple avec des limites connues
Exemples :
- Nginx Proxy Manager
- Traefik
- Gitea
- Grafana et Prometheus
- PostgreSQL plus une petite application web
- Uptime Kuma
- Services auxiliaires Home Assistant
- Registre privé
- API interne plus worker plus Redis
Compose est un bon choix lorsque le modèle opérationnel reste compréhensible par une seule personne lisant un seul répertoire.
Quand Docker Compose ne suffit pas
Utilisez autre chose lorsque vous avez besoin de :
- Planification multi-nœuds
- Réplanification automatique entre les hôtes
- Découverte de services au niveau du cluster
- Mise à l’échelle horizontale automatique
- Déploiements progressifs sur de nombreuses machines
- Identité de charge de travail fine
- Politiques réseau complexes
- Opérations de plateforme multi-équipes de grande envergure
À ce stade, Kubernetes, Nomad, Swarm ou une plateforme gérée peuvent être plus adaptés.
Ma règle pratique est d’éviter d’utiliser Kubernetes juste pour éviter d’apprendre systemd, et d’éviter d’utiliser Compose lorsque la charge de travail nécessite clairement une orchestration sur plusieurs hôtes.
L’architecture de base
Une configuration propre sépare les fichiers du projet, l’unité systemd et les données persistantes sur l’hôte. Le projet Compose réside sous /opt/myapp/ avec compose.yaml, .env, data/, backups/ et des scripts optionnels tels que scripts/update.sh. Le fichier unit systemd se trouve à /etc/systemd/system/myapp.service.
Chaque couche a un rôle clair : Docker exécute les conteneurs, Compose définit la pile d’application, systemd démarre et arrête le projet Compose au boot et à l’extinction, le système de fichiers de l’hôte stocke les données persistantes, les sauvegardes restent explicites, et les mises à jour passent par des étapes scriptées et révisables. Cette disposition est délibérément ennuyeuse, car une infrastructure ennuyeuse est plus facile à réparer lorsque quelque chose casse à 2 heures du matin.
Préparer le répertoire du projet Compose
Créez un répertoire sous /opt :
sudo mkdir -p /opt/myapp
sudo chown -R "$USER":"$USER" /opt/myapp
cd /opt/myapp
Créez un fichier Compose :
nano compose.yaml
Exemple :
services:
web:
image: nginx:stable
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
healthcheck:
test: ["CMD-SHELL", "nginx -t || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes: {}
Créez le répertoire de contenu :
mkdir -p html
echo "Hello from Docker Compose" > html/index.html
Testez d’abord manuellement :
docker compose up -d
docker compose ps
docker compose logs --tail=50
Ensuite, arrêtez-le avant de confier le cycle de vie à systemd :
docker compose down
Ne créez pas de service systemd tant que le projet Compose ne fonctionne pas manuellement. Pendant vos tests, gardez la Fiche de référence Docker Compose à portée de main pour ps, logs, pull et la structure du projet.
Utiliser la commande moderne docker compose
Docker Engine et le plugin Compose doivent être installés avant d’écrire un fichier unit. Sous Ubuntu, Installer Docker sur Ubuntu détaille APT, Snap, le mode sans privilèges et la sécurité post-installation pour que vous obteniez une commande docker compose fonctionnelle.
Utilisez ceci :
docker compose version
Pas ceci :
docker-compose version
L’ancien binaire docker-compose existe encore sur de nombreuses machines, mais Docker moderne utilise Compose en tant que plugin CLI Docker.
Dans les fichiers de service et les scripts, préférez :
/usr/bin/docker compose
Vous pouvez trouver le chemin Docker avec :
command -v docker
En général, c’est :
/usr/bin/docker
Créer un service systemd pour Docker Compose
Si les fichiers unit sont nouveaux pour vous, Exécuter n’importe quel exécutable en tant que service sous Linux explique Type, ExecStart, systemctl et le workflow général de systemd. Cette section applique ces modèles spécifiquement à une pile Compose.
Créez le fichier de service :
sudo nano /etc/systemd/system/myapp.service
Utilisez cette unité :
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Rechargez systemd :
sudo systemctl daemon-reload
Démarrez le service :
sudo systemctl start myapp.service
Activez-le au démarrage :
sudo systemctl enable myapp.service
Vérifiez l’état :
systemctl status myapp.service
Vérifiez les conteneurs :
cd /opt/myapp
docker compose ps
Pourquoi Type=oneshot et RemainAfterExit=yes ?
C’est la partie que de nombreux guides traitent de manière subtilement incorrecte.
docker compose up -d démarre les conteneurs en mode détaché et se termine, donc il n’y a pas de processus Compose en premier plan de longue durée pour que systemd puisse superviser. L’unité systemd ne devrait pas prétendre que docker compose up -d est un démon de longue durée.
Utilisez :
Type=oneshot
RemainAfterExit=yes
Cela indique à systemd :
- Exécuter la commande de démarrage.
- Considérer l’unité active après que la commande se soit terminée avec succès.
- Exécuter
ExecStoplorsque le service est arrêté.
Cela correspond au comportement réel de Compose détaché, c’est pourquoi Type=oneshot avec RemainAfterExit=yes est le paramètre par défaut correct pour la plupart des piles.
Pourquoi pas Type=simple ?
Avec Type=simple, systemd s’attend à ce que le processus ExecStart continue de s’exécuter, mais docker compose up -d se termine après avoir démarré les conteneurs. Cela peut amener systemd à penser que le service s’est terminé, puis à appeler la logique d’arrêt ou à marquer l’unité inactive selon la configuration.
Si vous voulez Type=simple, vous exécuteriez généralement Compose en premier plan :
ExecStart=/usr/bin/docker compose up
Cela peut fonctionner, mais je ne le préfère généralement pas pour les piles Compose sur les serveurs. Les conteneurs détachés plus ExecStop explicite sont plus faciles à exploiter.
Une unité plus adaptée à la production
Pour un serveur réel, je préfère une unité légèrement plus stricte :
[Unit]
Description=MyApp Docker Compose stack
Documentation=https://example.com/docs/myapp
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
EnvironmentFile=-/opt/myapp/.env.systemd
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Détails importants :
WorkingDirectorypointe vers le projet Compose.ExecStartPrevalide la configuration Compose.ExecReloadrecrée les services modifiés.ExecStoparrête et supprime les conteneurs du projet Compose et le réseau par défaut.EnvironmentFile=-...signifie que le fichier est optionnel.
Créez le fichier d’environnement systemd optionnel :
nano /opt/myapp/.env.systemd
Exemple :
COMPOSE_PROJECT_NAME=myapp
Ensuite, rechargez systemd :
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Compose .env vs EnvironmentFile systemd
Compose et systemd ont chacun leur propre mécanisme d’environnement, et les mélanger cause des échecs déroutants de « variable non définie » au démarrage.
Compose lit automatiquement un fichier .env dans le répertoire du projet pour la substitution de variables dans le fichier Compose.
Exemple .env :
APP_TAG=1.2.3
WEB_PORT=8080
Exemple compose.yaml :
services:
web:
image: nginx:${APP_TAG}
ports:
- "${WEB_PORT}:80"
Un EnvironmentFile systemd définit les variables d’environnement pour la commande docker compose elle-même.
Exemple :
EnvironmentFile=-/opt/myapp/.env.systemd
Pour de nombreux projets, vous n’avez besoin que de .env Compose.
Utilisez un fichier d’environnement systemd lorsque vous voulez définir des éléments tels que :
COMPOSE_PROJECT_NAME=myapp
COMPOSE_FILE=compose.yaml
DOCKER_HOST=unix:///var/run/docker.sock
N’utilisez aucun de ces fichiers comme coffre-fort de secrets décontracté. Si les secrets comptent, utilisez les secrets Docker, un gestionnaire de secrets externe, des fichiers chiffrés ou au moins des permissions strictes.
Définissez des permissions restrictives :
chmod 600 /opt/myapp/.env
chmod 600 /opt/myapp/.env.systemd
Politiques de redémarrage : Docker vs systemd
Il y a deux couches de redémarrage — la politique de redémarrage des conteneurs dans Compose et la politique de redémarrage du service systemd — et elles ne devraient pas être mélangées aveuglément.
Pour les conteneurs de longue durée, définissez les politiques de redémarrage dans Compose :
services:
web:
image: nginx:stable
restart: unless-stopped
Valeurs de redémarrage courantes :
| Politique | Signification |
|---|---|
| no | Ne pas redémarrer automatiquement |
| always | Redémarrer après sortie et redémarrage du daemon |
| on-failure | Redémarrer uniquement après échec |
| unless-stopped | Redémarrer sauf si arrêté manuellement |
Pour la plupart des services persistants, je préfère :
restart: unless-stopped
C’est prévisible et respecte les arrêts manuels intentionnels.
L’unité systemd elle-même ne devrait généralement pas redémarrer en boucle, car docker compose up -d n’est pas la charge de travail en cours. Ce sont les conteneurs.
Évitez donc ceci sauf si vous avez une raison spécifique :
Restart=always
Dans la plupart des unités Compose-en-service, laissez Docker gérer les redémarrages des conteneurs.
Contrôles de santé (Health Checks)
Les politiques de redémarrage redémarrent les conteneurs lorsque les processus se terminent. Elles ne corrigent pas magiquement chaque application malsaine.
Ajoutez des contrôles de santé là où ils sont utiles :
services:
app:
image: example/app:latest
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
Vérifiez la santé :
docker compose ps
Inspectez un conteneur :
docker inspect container-name
Les contrôles de santé sont particulièrement utiles pour :
- Applications web
- Proxies inverses
- Bases de données
- Files d’attente
- API internes
- Workers avec un point de terminaison de santé
Ils sont moins utiles lorsqu’ils ne vérifient que l’existence d’un processus, car un processus vivant mais bloqué semble toujours en bonne santé. Un mauvais contrôle de santé n’est qu’un autre mensonge en YAML.
Ordre de démarrage et depends_on
Compose peut définir des dépendances :
services:
app:
image: example/app:latest
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Cela peut aider l’ordre de démarrage, mais ne faites pas trop confiance. Les applications devraient toujours gérer les tentatives — les bases de données redémarrent, les réseaux fluctuent, le DNS prend du temps, et une application résiliente réessaie les connexions au lieu de supposer un ordre de démarrage parfait.
Journaux : journalctl et docker compose logs
Deux vues de journaux couvrent la plupart du débogage : systemd capture le cycle de vie de l’unité elle-même, tandis que Compose capture la sortie de l’application des conteneurs en cours d’exécution.
Journaux du service systemd :
journalctl -u myapp.service -n 100 --no-pager
Suivre les journaux systemd :
journalctl -u myapp.service -f
Journaux du service Compose :
cd /opt/myapp
docker compose logs --tail=100
docker compose logs -f
docker compose logs -f web
Pour la plupart des débogages d’application, docker compose logs est plus utile ; pour le débogage du cycle de vie — échecs de démarrage, plantages d’unité, erreurs de permissions — journalctl est plus utile. Si systemctl start myapp échoue, vérifiez journalctl en premier. Si la pile démarre mais que l’application est cassée, vérifiez docker compose logs.
Rotation des journaux
Les journaux Docker peuvent croître indéfiniment si vous ne les configurez pas.
Pour les petits serveurs, configurez la rotation des journaux Docker dans /etc/docker/daemon.json :
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
Redémarrez Docker :
sudo systemctl restart docker
Ensuite, redémarrez la pile Compose :
sudo systemctl restart myapp.service
Cela s’applique aux conteneurs nouvellement créés. Recréez les conteneurs si nécessaire :
cd /opt/myapp
docker compose up -d --force-recreate
La rotation des journaux n’est pas glamour, mais c’est l’un des moyens les plus simples d’empêcher une panne de disque plein sur un petit serveur.
Mettre à jour un service Compose
Un flux de mise à jour manuel simple :
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
Si géré par systemd, vous pouvez utiliser :
sudo systemctl reload myapp.service
Si votre unité a :
ExecReload=/usr/bin/docker compose up -d --remove-orphans
Mais notez : ExecReload ne télécharge pas les images à moins que vous n’incluez cette étape.
Pour des mises à jour explicites, créez un script.
mkdir -p /opt/myapp/scripts
nano /opt/myapp/scripts/update.sh
Script :
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
docker compose config --quiet
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
docker compose ps
Rendez-le exécutable :
chmod +x /opt/myapp/scripts/update.sh
Exécutez-le :
/opt/myapp/scripts/update.sh
Ensuite, l’unité de service peut rester focalisée sur le cycle de vie, tandis que le script de mise à jour gère le déploiement.
Script de mise à jour plus sûr avec sauvegarde
Pour les services avec état, mettez à jour uniquement après sauvegarde.
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/myapp/backups"
cd "$APP_DIR"
mkdir -p "$BACKUP_DIR"
echo "Validation du fichier compose"
docker compose config --quiet
echo "Exécution de la sauvegarde"
if [ -x "$APP_DIR/scripts/backup.sh" ]; then
"$APP_DIR/scripts/backup.sh"
else
echo "Aucun hook de sauvegarde trouvé"
fi
echo "Téléchargement des images"
docker compose pull
echo "Recréation des services"
docker compose up -d --remove-orphans
echo "Nettoyage des images inutilisées"
docker image prune -f
echo "État actuel"
docker compose ps
Ceci est toujours simple, mais encode maintenant une habitude opérationnelle : sauvegarder avant de changer.
Arrêter le service
Arrêtez la pile :
sudo systemctl stop myapp.service
Cela exécute :
docker compose down
Par défaut, docker compose down supprime :
- Les conteneurs pour les services dans le fichier Compose
- Les réseaux définis par le fichier Compose
- Le réseau par défaut
Il ne supprime pas les volumes nommés à moins que vous ne le lui demandiez.
N’utilisez pas casually :
docker compose down -v
Cela supprime les volumes nommés déclarés dans le fichier Compose et les volumes anonymes attachés aux conteneurs. Pour les bases de données et les applications avec état, cela peut signifier supprimer de vraies données.
Utilisez down -v uniquement lorsque vous voulez dire “détruire cet environnement”.
Redémarrer le service
Redémarrez l’unité systemd :
sudo systemctl restart myapp.service
Cela exécute la commande d’arrêt puis la commande de démarrage.
Pour ne redémarrer que les conteneurs sans les recréer :
cd /opt/myapp
docker compose restart
Distinction importante :
docker compose restartredémarre les conteneurs existants.docker compose up -dapplique les modifications de configuration ou d’image en recréant les conteneurs si nécessaire.
Si vous avez modifié compose.yaml, utilisez :
docker compose up -d
Pas juste :
docker compose restart
Gérer les conteneurs orphelins
Si vous renommez ou supprimez un service dans compose.yaml, les anciens conteneurs peuvent rester comme orphelins.
Utilisez :
docker compose up -d --remove-orphans
C’est pourquoi les exemples de service systemd de ce guide utilisent :
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Cela garde la pile plus proche du fichier Compose actuel.
Sauvegardes
Les sauvegardes dépendent de la charge de travail, mais les principes sont stables.
Pour les montages de liaison :
/opt/myapp/data/
Sauvegardez ce répertoire.
Pour les volumes nommés :
docker volume ls
Inspectez un volume :
docker volume inspect volume-name
Pour les bases de données, les copies de système de fichiers ne suffisent pas toujours. Utilisez des sauvegardes conscientes de l’application :
Exemple PostgreSQL :
docker compose exec -T db pg_dump -U postgres appdb > backups/appdb.sql
Exemple MariaDB :
docker compose exec -T db mariadb-dump -u root -p appdb > backups/appdb.sql
Exemple Redis :
docker compose exec redis redis-cli BGSAVE
Une pile Compose sans plan de sauvegarde n’est pas un service — c’est une expérience temporaire qui a la chance d’avoir du temps de fonctionnement.
Sécurité de base
Pour un petit service Compose sur Linux, commencez par cette base :
- Gardez le projet Compose sous
/opt/appname. - Utilisez des tags d’image explicites, pas seulement
latest, lorsque la stabilité compte. - Utilisez les montages de liaison ou les volumes nommés délibérément.
- N’exposez pas les ports dont vous n’avez pas besoin.
- Placez les services publics derrière un proxy inverse.
- Utilisez HTTPS à la périphérie.
- Gardez les secrets hors de Git.
- Restreignez les permissions de
.env. - Évitez les conteneurs privilégiés sauf si réellement requis.
- Évitez de monter le socket Docker dans les conteneurs.
- Gardez Docker et les images à jour.
- Testez le comportement du pare-feu depuis une autre machine.
Un modèle dangereux :
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Cela donne au conteneur le contrôle sur Docker. En pratique, cela peut devenir un contrôle au niveau de l’hôte. Utilisez-le uniquement lorsque vous comprenez le risque.
Limites de ressources
Sur les petits serveurs, un seul mauvais conteneur peut consommer l’hôte.
Compose prend en charge les paramètres liés aux ressources, mais le comportement peut dépendre de la version de Docker Engine et Compose. Pour une protection simple, commencez par les limites au niveau de l’application et les limites de journalisation Docker.
Pour certaines charges de travail, vous pouvez ajouter des limites de mémoire :
services:
app:
image: example/app:stable
restart: unless-stopped
mem_limit: 512m
Configurez également les nombres de workers au niveau de l’application, les limites de file d’attente et les tailles de cache. Les limites des conteneurs sont utiles, mais elles ne remplacent pas la compréhension de l’application.
Exemple : Un service Compose réaliste
Répertoire :
/opt/whoami/
compose.yaml
.env
Fichier Compose :
services:
whoami:
image: traefik/whoami:v1.10
restart: unless-stopped
ports:
- "${WHOAMI_PORT}:80"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost || exit 1"]
interval: 30s
timeout: 5s
retries: 3
Fichier .env :
WHOAMI_PORT=8080
COMPOSE_PROJECT_NAME=whoami
Unité systemd :
[Unit]
Description=Whoami Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/whoami
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Installez-le :
sudo systemctl daemon-reload
sudo systemctl enable --now whoami.service
Testez :
curl http://localhost:8080
Vérifiez l’état :
systemctl status whoami.service
cd /opt/whoami
docker compose ps
Dépannage
Le service démarre mais les conteneurs ne sont pas en cours d’exécution
Vérifiez systemd :
journalctl -u myapp.service -n 100 --no-pager
Validez Compose :
cd /opt/myapp
docker compose config
Vérifiez Docker :
systemctl status docker
docker info
WorkingDirectory est incorrect
Si systemd ne peut pas trouver votre fichier Compose, confirmez :
WorkingDirectory=/opt/myapp
Ensuite, vérifiez :
ls -la /opt/myapp
ls -la /opt/myapp/compose.yaml
Le service s’exécute depuis WorkingDirectory, pas depuis votre répertoire de shell actuel.
Permission refusée Docker
Si l’unité s’exécute en tant que root, elle peut normalement accéder à Docker.
Si vous définissez User=someuser, cet utilisateur doit pouvoir accéder à Docker. Habituellement, cela signifie l’appartenance au groupe docker, ou une configuration Docker sans privilèges.
Vérifiez :
groups someuser
Ajoutez l’utilisateur si approprié :
sudo usermod -aG docker someuser
Soyez prudent. Le groupe Docker est effectivement privilégié.
Commande Compose introuvable
Trouvez Docker :
command -v docker
Utilisez le chemin complet dans l’unité :
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Si le plugin Compose est manquant :
docker compose version
Installez-le en utilisant votre source de package Docker.
Variables d’environnement manquantes
Vérifiez la configuration Compose telle que systemd la verrait :
cd /opt/myapp
docker compose config
Si systemd a besoin de variables d’environnement supplémentaires, utilisez :
EnvironmentFile=-/opt/myapp/.env.systemd
Si Compose a besoin de variables pour la substitution, utilisez :
/opt/myapp/.env
Ces éléments sont liés, mais ne sont pas identiques.
Les conteneurs ne démarrent pas après le redémarrage
Vérifiez si le service systemd est activé :
systemctl is-enabled myapp.service
Activez-le :
sudo systemctl enable myapp.service
Vérifiez Docker :
systemctl is-enabled docker
systemctl status docker
Vérifiez les journaux de démarrage :
journalctl -u myapp.service -b --no-pager
L’application démarre avant que la base de données ne soit prête
Ajoutez un contrôle de santé de base de données et depends_on avec service_healthy.
Corrigez également l’application. Elle devrait réessayer les connexions à la base de données. L’ordre de démarrage de l’infrastructure est utile, mais la logique de tentative de l’application est meilleure.
Disque rempli avec les journaux Docker
Vérifiez l’utilisation du disque Docker :
docker system df
Vérifiez les journaux de conteneurs volumineux :
sudo du -h /var/lib/docker/containers | sort -h | tail
Configurez la rotation des journaux Docker dans /etc/docker/daemon.json.
Ensuite, recréez les conteneurs.
Erreurs courantes
Erreur 1 : Exécuter docker compose up dans rc.local
Exécuter docker compose up depuis rc.local ou un script de connexion fonctionne jusqu’à ce que cela ne fonctionne plus — utilisez une unité systemd appropriée à la place.
Erreur 2 : Utiliser Restart=always dans systemd et restart: always dans Compose
Généralement, vous n’avez besoin que des politiques de redémarrage des conteneurs dans Compose. Évitez que deux superviseurs ne se battent.
Erreur 3 : Oublier –remove-orphans
Les renommages et suppressions de services peuvent laisser d’anciens conteneurs derrière. Utilisez :
docker compose up -d --remove-orphans
Erreur 4 : Utiliser docker compose restart après des modifications de configuration
restart redémarre les conteneurs. Il n’applique pas toutes les modifications de configuration.
Utilisez :
docker compose up -d
Erreur 5 : Exécuter down -v sans réfléchir
Cela peut supprimer des volumes. Pour les services avec état, cela peut signifier supprimer des données.
Erreur 6 : Pas de sauvegarde avant Pull
De nouvelles images peuvent casser. Les bases de données peuvent migrer. Les tags peuvent bouger. Sauvegardez d’abord.
Erreur 7 : Publier chaque port
Ne publiez que ce que l’hôte a besoin d’exposer. Le trafic interne service-à-service peut rester sur le réseau Compose.
Modèle final recommandé
Pour la plupart des services Linux sur un seul hôte, utilisez ce modèle :
Fichier Compose :
services:
app:
image: example/app:stable
restart: unless-stopped
ports:
- "8080:8080"
env_file:
- .env
Unité systemd :
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Activez-le :
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
Exploitez-le :
sudo systemctl status myapp.service
sudo systemctl restart myapp.service
journalctl -u myapp.service -f
cd /opt/myapp && docker compose logs -f
Ce modèle n’est pas fancy, et c’est le but. Docker Compose est excellent pour les petits systèmes compréhensibles, systemd est excellent pour démarrer et arrêter les services de l’hôte, et ensemble, ils vous offrent un modèle de déploiement sur un seul serveur fiable sans prétendre que chaque projet a besoin d’un cluster. Pour les commandes au niveau des conteneurs en dehors de Compose — images, volumes, réseaux et nettoyage — consultez la Fiche de référence Docker.