SSD Nodes Learn 8GB de RAM — $66/an
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-02

Docker Compose : .env, env_file ou environment ?

Comprenez la différence entre .env, env_file et environment dans Docker Compose, leur ordre de priorité et pourquoi les secrets ne doivent pas rester dans les variables d’environnement.

Les trois éléments que l’on appelle un fichier env

Docker Compose dispose de trois mécanismes distincts aux noms très similaires. Le fichier .env remplace les variables ${VARIABLE} dans compose.yaml, avant même que Compose n’analyse le fichier. L’attribut env_file: charge un fichier contenant des paires clé/valeur dans l’environnement du conteneur. L’attribut environment: définit directement des variables sur le conteneur, dans le fichier Compose. Ces mécanismes ne sont pas interchangeables. Lorsque deux d’entre eux définissent la même clé, la valeur retenue suit un ordre de priorité documenté.

Ce guide montre chaque mécanisme en fonctionnement. Il vérifie l’ordre de priorité avec une commande que vous pouvez exécuter. Il traite ensuite du point le plus important : les variables d’environnement sont lisibles par toute personne pouvant exécuter docker inspect. Les mots de passe ne doivent donc pas y être stockés. Si vous débutez avec les fichiers Compose, commencez par les bases de Docker Compose sur un VPS, puis revenez ici pour la configuration.

Le fichier .env est destiné au fichier Compose, pas au conteneur

Créez un répertoire et placez-y deux fichiers.

mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .env
services:
  demo:
    image: alpine:${ALPINE_TAG}
    command: printenv ALPINE_TAG

Demandez maintenant à Compose ce qu’il a réellement analysé.

docker compose config

La sortie affiche image: alpine:3.20. Le paramètre fictif a disparu, car l’interpolation a eu lieu lors de l’analyse. Compose recherche .env dans le répertoire du projet, c’est-à-dire le répertoire qui contient le fichier Compose, puis remplace chaque occurrence de ${NAME}.

Lancez ensuite le service.

docker compose run --rm demo

printenv ALPINE_TAG se termine avec le code d’état 1 et n’affiche rien. La variable n’existe pas dans le conteneur. C’est le malentendu le plus courant : .env a configuré le fichier Compose, pas le processus. Un fichier .env contenant POSTGRES_PASSWORD=hunter2 n’a aucun effet sur votre base de données, sauf si une partie du fichier Compose le référence.

${NAME:-default} fournit une valeur de secours lorsque la variable n’est pas définie ou est vide. ${NAME:?message} demande à Compose de refuser le démarrage et d’afficher votre message. C’est le bon choix pour une valeur qui ne possède aucune valeur par défaut sûre.

env_file charge des variables dans le conteneur

L’attribut env_file: désigne un ou plusieurs fichiers dont le contenu devient des variables d’environnement du conteneur.

printf 'GREETING=from_env_file\nAPP_MODE=production\n' > app.env
services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
docker compose run --rm demo

Cette commande affiche from_env_file. Le format du fichier consiste en lignes KEY=value simples, une par ligne. Un caractère # au début d’une ligne introduit un commentaire. Ce n’est pas du shell. Dans la plupart des cas, les guillemets sont conservés dans la valeur. Les préfixes export ne sont pas nécessaires. Ne mettez pas d’espaces autour du signe =, car KEY = value crée une variable nommée littéralement KEY , dont la valeur commence par une espace.

Un chemin env_file manquant est une erreur et Compose s’arrête. Marquez-le comme facultatif si le fichier peut légitimement être absent :

    env_file:
      - path: ./app.env
        required: false

environment définit les variables inline

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    environment:
      GREETING: from_environment

Deux syntaxes sont acceptées : la forme de mappage ci-dessus et une forme de liste utilisant - GREETING=from_environment. Elles se comportent de manière identique. La forme de liste offre une possibilité supplémentaire : une clé seule, sans valeur, transmet la variable depuis le shell dans lequel vous avez exécuté docker compose.

    environment:
      - GREETING
GREETING=from_my_shell docker compose run --rm demo

Cela affiche from_my_shell. Exécutez cette commande sans définir GREETING dans le shell : Compose ne définit rien et n’affiche aucun avertissement. Les échecs silencieux de transmission sont importants à connaître, car un service qui démarre avec une variable de mot de passe vide démarre souvent correctement, tout en étant entièrement ouvert.

Lequel est prioritaire

Docker documente l’ordre de priorité, du plus élevé au plus faible : docker compose run -e sur la ligne de commande, puis environment ou env_file dont la valeur est interpolée depuis votre shell ou un fichier env, puis environment simple dans le fichier Compose, puis env_file, puis la directive ENV intégrée à l’image.

La version courte pour le travail quotidien : environment: est prioritaire sur env_file:, et -e sur la ligne de commande est prioritaire sur les deux. Vérifiez-le dans un seul fichier.

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
    environment:
      GREETING: from_environment
docker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETING

La première commande affiche from_environment : environment: a donc remplacé la valeur de app.env. La seconde affiche from_cli. Rien dans le fichier Compose ne remplace la valeur fournie sur la ligne de commande.

Lorsqu’un conteneur se comporte comme si votre configuration n’avait jamais été appliquée, ne faites pas de suppositions. docker compose config affiche le fichier entièrement résolu, et docker compose config --environment affiche les variables d’interpolation utilisées par Compose. La plupart des signalements du type « mon fichier env est ignoré » s’expliquent par une valeur définie deux fois, à deux niveaux différents.

Pourquoi les variables d’environnement fuient

Définissez un mot de passe dans environment: : il est alors stocké sur disque dans la configuration du conteneur et visible par tous les utilisateurs du groupe docker.

docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'

La sortie contient "DB_PASSWORD=hunter2" en clair. Trois autres chemins exposent la même valeur. docker compose config l’affiche dans le terminal, qui est ainsi copiée-collée dans un forum d’assistance. Tout processus exécuté dans le conteneur peut lire /proc/1/environ, et chaque processus enfant hérite de la variable. En outre, les gestionnaires de plantage des applications consignent régulièrement tout l’environnement dans un journal ou un rapport d’erreur.

L’appartenance au groupe docker équivaut de fait à disposer des droits root sur l’hôte. Vous ne pouvez donc pas compter sur ce groupe comme frontière de privilèges. Le guide comptes utilisateur appliquant le principe du moindre privilège sur un VPS explique pourquoi il est préférable de limiter ce groupe sur tout serveur partagé.

Les secrets Compose conservent la valeur dans un fichier

Compose prend en charge les secrets fondés sur des fichiers. La valeur est montée dans le conteneur sous forme de fichier, au lieu d’être injectée dans l’environnement.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
secrets:
  db_password:
    file: ./db_password.txt

Le secret est monté à l’emplacement /run/secrets/db_password dans le conteneur. Le nom après la barre oblique correspond au nom du secret défini dans le bloc secrets: de niveau supérieur.

Le suffixe _FILE est une convention utilisée par les Docker Official Images, notamment postgres, mysql et mariadb. Leurs scripts d’entrypoint recherchent VARNAME_FILE, lisent le fichier et utilisent son contenu. Ce n’est pas une fonctionnalité de Docker. Cela fonctionne uniquement si l’image l’implémente. Consultez la documentation de l’image avant de supposer que SOMETHING_FILE sera pris en charge. Les applications qui ne prennent pas cette fonctionnalité en charge peuvent souvent lire elles-mêmes le fichier au démarrage. Vous pouvez également transmettre le chemin et laisser votre propre entrypoint s’en charger.

Vérifiez le résultat depuis le conteneur en cours d’exécution :

docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORD

La première commande affiche le mot de passe. La seconde n’affiche rien, car la valeur n’a jamais été placée dans l’environnement. C’est tout l’objectif : docker inspect dans ce conteneur affiche uniquement le chemin sans risque.

Protégez le fichier source sur l’hôte, car le secret n’est pas plus confidentiel que le fichier qui le contient :

chmod 600 db_password.txt

Le compromis pragmatique sur un VPS

De nombreuses images auto-hébergées ne prennent pas en charge les variables _FILE. Les variables d’environnement sont donc le seul moyen de les fournir. Sur un VPS administré par une seule personne, l’objectif réaliste consiste à éviter que les valeurs restent dans un fichier lisible par tous dans le répertoire du projet, et à les exclure de git.

sudo install -o root -g root -m 600 /dev/null /etc/myapp/app.env
sudo nano /etc/myapp/app.env
    env_file:
      - /etc/myapp/app.env

install -m 600 crée le fichier avec les permissions déjà définies. Il n’existe donc aucune période pendant laquelle il est lisible par tous. root en est propriétaire. Un utilisateur sans privilèges sur la machine ne peut donc pas le lire, mais toute personne pouvant exécuter docker peut toujours lire la valeur depuis le conteneur. Ajoutez *.env et .env à .gitignore, puis validez un fichier app.env.example contenant les noms des clés avec des valeurs vides. Un mot de passe validé dans le dépôt doit être renouvelé.

Renouveler une valeur implique de redémarrer le service. Les variables d’environnement sont lues une seule fois au démarrage du processus du conteneur. Modifier le fichier ne change donc rien tant que vous n’exécutez pas docker compose up -d --force-recreate db. C’est le même schéma que celui utilisé dans le guide n8n derrière HTTPS sur un VPS, où la clé de chiffrement se trouve en dehors du fichier compose.

Séparer la configuration par environnement

Compose lit .env depuis le répertoire du projet par défaut. Utilisez --env-file pour spécifier un autre emplacement.

docker compose --env-file .env.staging config

Les fichiers sont lus dans l’ordre, et les fichiers suivants remplacent les valeurs définies précédemment. Conservez les valeurs par défaut non secrètes dans un fichier versionné, et les secrets dans un fichier qui ne quitte jamais le serveur. La même règle s’applique à env_file: : en cas de clé dupliquée, le dernier fichier indiqué prévaut.

FAQ

Pourquoi mon fichier .env est-il ignoré dans le conteneur ?

Il n’est pas ignoré. Le fichier .env remplace uniquement les variables ${NAME} dans le fichier Compose. Il ne définit jamais de variables dans un conteneur. Pour transmettre la valeur au conteneur, référencez-la avec environment: { KEY: "${NAME}" } ou utilisez plutôt env_file: ./that-file.env.

La section environment remplace-t-elle env_file, ou est-ce l’inverse ?

environment: est prioritaire. Selon l’ordre documenté par Docker, l’attribut environment est prioritaire sur l’attribut env_file, et tous deux sont moins prioritaires que docker compose run -e sur la ligne de commande. Si une clé est définie aux deux endroits, la valeur de env_file est ignorée sans message.

Comment voir la valeur finale utilisée par Compose ?

Exécutez docker compose config pour afficher le fichier Compose entièrement résolu, après toutes les interpolations. Pour un conteneur déjà en cours d’exécution, docker inspect <container> --format '{{json .Config.Env}}' affiche exactement ce que son processus a reçu.

Les secrets Compose sont-ils chiffrés ?

Non. Un secret basé sur un fichier est monté dans le conteneur comme un fichier en clair à l’emplacement /run/secrets/<name>, et le fichier source reste non chiffré sur le disque de l’hôte. L’avantage concerne la portée, pas le chiffrement : la valeur reste absente de l’environnement du conteneur, de la sortie de docker inspect et des core dumps qui affichent l’environnement.

Puis-je utiliser des guillemets et des espaces dans un fichier env ?

Utilisez KEY=value with spaces et ne mettez pas de guillemets. Compose traite tout le reste de la ligne comme la valeur. Les guillemets deviennent donc généralement des caractères littéraux dans la valeur. Ne mettez jamais d’espaces autour de =, car la clé comporte alors un espace final et aucune correspondance n’est trouvée.