Les variables d’environnement n’atteignent pas le conteneur
Quand les variables d’environnement ne fonctionnent pas dans un conteneur, l’une de cinq raisons est généralement en cause : build versus runtime, bundling frontend, guillemets, redémarrage ou mauvais scope. Vérifiez-les dans cet ordre.
Vous définissez la variable. Le dashboard l’affiche. L’application indique qu’elle est undefined. Les variables d’environnement qui ne fonctionnent pas dans un conteneur sont l’un des problèmes de configuration les plus courants dans l’hébergement d’applications, et il s’agit presque toujours de l’une de cinq causes précises.
Elles sont présentées ici dans l’ordre qui permet de trouver le problème le plus rapidement.
1. Le build et le runtime sont deux mondes différents
C’est la cause de la majorité de ces problèmes, et c’est aussi celle qui paraît le moins intuitive.
Les variables définies sur votre service existent lorsque le conteneur s’exécute. Tout ce que fait votre Dockerfile se produit plus tôt, dans un environnement distinct. Une étape RUN ne peut pas voir une variable de runtime, puisqu’à ce moment-là, il n’y a pas encore de runtime.
# This is empty during build. Always.
RUN echo $DATABASE_URL
# This is available at runtime, because it is the running process reading it
CMD ["node", "server.js"]
Si vous avez réellement besoin d’une valeur pendant le build, elle doit être transmise comme argument de build — un mécanisme différent, avec des propriétés de sécurité différentes :
ARG BUILD_VERSION
RUN echo "Building $BUILD_VERSION"
Ne transmettez jamais un secret de cette manière. Les arguments de build sont enregistrés dans l’historique des layers de l’image. Toute personne pouvant télécharger l’image peut les lire.
2. Les variables frontend sont intégrées au build, elles ne sont pas lues
Si votre frontend indique undefined en production, c’est presque certainement la raison.
Un navigateur ne possède pas d’environnement. Quand vous écrivez import.meta.env.VITE_API_URL ou process.env.NEXT_PUBLIC_API_URL, le bundler remplace cette expression par la chaîne littérale au moment du build. Aucune recherche n’est effectuée dans le navigateur : la valeur a été compilée dans le bundle.
Trois conséquences piègent souvent les utilisateurs :
- Modifier la variable ne change rien tant que vous ne reconstruisez pas l’application. L’ancienne valeur se trouve dans le fichier JavaScript.
- Le préfixe est obligatoire. Vite n’expose que les variables
VITE_, et Next.js uniquement celles qui commencent parNEXT_PUBLIC_. Une variable sans ce préfixe est volontairement masquée. - Tout ce qui est exposé de cette manière est public. La valeur se trouve dans un fichier que vous servez à n’importe qui. Ne placez jamais un secret derrière
NEXT_PUBLIC_, malgré ce que son nom peut laisser penser.
C’est également la raison pour laquelle une image préconstruite ne peut pas être configurée de cette manière après coup. Si l’image a été construite ailleurs avec les valeurs compilées, définir des variables sur le service ne change rien : les chaînes sont déjà présentes dans le bundle.
3. Les guillemets
Les valeurs contenant des caractères spéciaux sont modifiées de manière imprévisible, ce qui produit des erreurs déroutantes plutôt que des erreurs évidentes.
# The shell eats everything after #
dockup env set DB_PASS=p@ss#word my-project/my-api
# Quote it
dockup env set 'DB_PASS=p@ss#word' my-project/my-api
Les caractères concernés sont les suivants : # (commentaire), $ (expansion), les espaces (découpage des arguments), ! (expansion de l’historique dans un bash interactif) et les retours à la ligne — qui apparaissent dans un seul cas courant : les clés privées.
Les valeurs multilignes sont les plus problématiques. Une clé PEM collée dans un champ sur une seule ligne est reçue sans ses retours à la ligne et produit une erreur d’analyse qui ne mentionne aucunement ces retours. Encodez-la en Base64, puis décodez-la dans l’application :
dockup env set "PRIVATE_KEY_B64=$(base64 -i key.pem)" my-project/my-api
4. Vous n’avez pas redémarré
Les variables d’environnement sont lues par un processus au moment de son démarrage. Les modifier affecte le prochain processus, pas celui qui s’exécute actuellement.
La plupart des plateformes gèrent ce cas en redéployant automatiquement l’application lorsque la configuration change, mais ce n’est pas toujours le cas. De plus, une modification partielle — définir trois variables, redéployer, puis en définir une quatrième — laisse cette dernière de côté.
dockup env list my-project/my-api --json # what is configured
dockup restart my-project/my-api # make the process re-read it
La vérification qui permet de trancher consiste à lire la variable depuis le conteneur en cours d’exécution, et non depuis le dashboard.
dockup exec "printenv | sort" my-project/my-api
Si elle apparaît dans cette sortie alors que votre application indique toujours undefined, le problème vient de votre code. Si elle n’apparaît pas, le problème vient de la configuration. Cette seule commande réduit de moitié le champ des recherches.
5. Mauvais scope
Les variables sont généralement limitées à un service, un environnement ou un projet. Une variable définie en production n’est pas visible dans un environnement de preview. De même, une variable définie sur un autre service du même projet ne sera pas visible.
C’est la cause habituelle lorsqu’une fonctionnalité fonctionne à un endroit, mais pas à un autre avec un code identique.
L’ordre du diagnostic
# 1. Is it actually in the container's environment?
dockup exec "printenv | sort" my-project/my-api
# 2. Is it configured on the service you think it is?
dockup env list my-project/my-api --json
# 3. Is the running process older than the change?
dockup status my-project/my-api --json
Commencez toujours par l’étape 1. Elle transforme un problème ambigu en l’un de deux problèmes parfaitement identifiables.
Les secrets en particulier
Deux habitudes méritent d’être adoptées, quelle que soit la plateforme.
Marquez les secrets comme tels. Sur Dockup, une variable marquée comme secret est masquée dans les listes et les réponses d’API : dockup env list affiche ******** au lieu de sa valeur. C’est plus important qu’il n’y paraît, car la manière la plus courante dont un identifiant fuit n’est pas une attaque : c’est une capture d’écran, un ticket de support ou une ligne de log.
Gardez-les en dehors des arguments de build et des bundles frontend. Les deux sont lisibles par toute personne qui obtient l’artefact. La règle générale est simple : si une valeur finit dans un fichier que vous distribuez, ce n’est plus un secret.
Foire aux questions
Pourquoi ma variable d’environnement est-elle undefined au moment du build ? Parce que le build et le runtime sont deux environnements distincts. Les variables de runtime n’existent pas pendant la construction de l’image. Utilisez un argument de build si vous avez réellement besoin d’une valeur pendant le build — mais jamais pour un secret.
Pourquoi mon frontend ne voit-il pas la variable ?
Les bundlers remplacent la valeur au moment du build et n’exposent que les noms préfixés — VITE_, NEXT_PUBLIC_. Modifier la variable nécessite un nouveau build, et toute valeur exposée de cette manière est lisible publiquement.
Dois-je redémarrer après avoir modifié une variable ?
Oui. Un processus en cours d’exécution a déjà lu son environnement. La plupart des plateformes redéploient automatiquement l’application après une modification ; vérifiez toutefois avec printenv depuis le conteneur plutôt que de vous fier au dashboard.
Comment transmettre une valeur multiligne comme une clé privée ? Encodez-la en Base64, définissez la chaîne encodée, puis décodez-la dans l’application. Les champs de variables d’environnement sur une seule ligne suppriment les retours à la ligne et produisent des erreurs d’analyse qui ne les mentionnent pas.
