Le vrai problème#
Je fais tourner des services sur mon serveur domestique avec Docker Compose depuis plusieurs mois. Récemment, j’ai tenté de configurer un mot de passe avec des caractères spéciaux dans mon fichier .env. Le mot de passe ressemblait à Pass$word123!@. Au démarrage des conteneurs, la variable arrivait vide ou malformée. Après investigation, j’ai découvert que Docker Compose interprétait le $ comme référence à une autre variable.
Pourquoi c’est arrivé : interpolation de variables#
Docker Compose interprète le fichier .env de façon spéciale. Quand il trouve un $ suivi d’un nom de variable valide, il essaie de le substituer par sa valeur. Si cette variable n’existe pas, il la laisse vide ou génère une erreur silencieuse.
Exemple du problème :
# .env
DB_PASSWORD=Pass$word123
API_KEY=sk_test_$random_key
SECRET=$UNDEFINED_VARDans ces cas, Docker Compose cherchera des variables appelées word123, random_key et UNDEFINED_VAR. Évidemment il ne les trouvera pas, et tes valeurs seront corrompues.
La solution : guillemets simples#
La solution la plus fiable est d’entourer les valeurs avec des guillemets simples. Les guillemets simples empêchent l’interpolation de variables dans Docker Compose, exactement comme ça fonctionne dans bash.
# .env - FORMA CORRECTA
DB_PASSWORD='Pass$word123'
API_KEY='sk_test_$random_key'
SECRET='$UNDEFINED_VAR'
COMPLEX='!@#$%^&*()'Avec des guillemets simples, Docker Compose traite tout le contenu comme du texte littéral. Il ne tente pas de résoudre les références à des variables.
Utiliser les variables dans docker-compose.yml#
Une fois définies correctement dans .env, les utiliser dans ton docker-compose.yml est normal :
version: '3.8'
services:
database:
image: postgres:15
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USER}
api:
image: mi-api:latest
environment:
API_KEY: ${API_KEY}
DB_SECRET: ${SECRET}Docker Compose chargera les valeurs depuis .env et injectera les variables correctement dans les conteneurs.
Le second problème : restart ne recharge pas les variables#
C’est là que c’est frustrant. Après avoir modifié ton fichier .env, tu exécutes :
docker-compose restartEt tu découvres que les conteneurs utilisent toujours les anciennes valeurs. Cela arrive parce que restart ne redémarre que les conteneurs existants sans les recréer. Il ne relit pas le fichier .env.
La solution : –force-recreate#
Pour que Docker Compose relise le fichier .env et applique les nouvelles variables, tu dois recréer les conteneurs. La commande correcte est :
docker-compose up -d --force-recreateOu si tu préfères une séquence plus explicite :
docker-compose down
docker-compose up -dL’option --force-recreate force la recréation même si l’image n’a pas changé. Sans elle, Docker Compose pourrait réutiliser des conteneurs existants.
Mon flux de travail actuel#
Après expérimenter avec ça, voici comment je gère les variables sur mon serveur :
Je définis tout dans
.envavec des guillemets simples :MYSQL_ROOT_PASSWORD='R00t!$pecial#Pass' MYSQL_USER='admin' MYSQL_PASSWORD='Pass$word@123'Référence dans
docker-compose.yml:environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_PASSWORD: ${MYSQL_PASSWORD}Après modification de
.env, j’utilise toujours :docker-compose up -d --force-recreateJe vérifie que les changements se sont appliqués :
docker-compose exec servicio env | grep MI_VAR
Leçons apprises#
- Les caractères spéciaux
$,!,@,#dans les valeurs nécessitent des guillemets simples restartredémarre seulement, ne recharge pas la configuration--force-recreateest indispensable après modification de.env- Vérifie toujours que les variables ont été correctement chargées à l’intérieur du conteneur
Ces détails m’ont épargné de nombreuses heures de debugging sur mon setup domestique. J’espère qu’ils t’en épargneront aussi.
Équipement recommandé#
- Raspberry Pi 3 B+ — Serveur léger à faible consommation pour démarrer ton homelab
- Raspberry Pi 4 (4GB) — La base parfaite pour homelab, Docker et monitoring
Liens d’affiliation. Sans coût supplémentaire pour toi.