A környezeti változók nem jutnak el a konténerbe
Ha a környezeti változók nem működnek egy konténerben, annak általában öt oka van: build időpontja kontra futási idő, frontend-bundling, idézőjelek használata, újraindítási időzítés vagy nem megfelelő hatókör. Ellenőrizd őket ebben a sorrendben.
Beállítod a változót. A dashboard megjeleníti. Az alkalmazás szerint az érték undefined. Ha a környezeti változók nem működnek egy konténerben, az az alkalmazások üzemeltetésének egyik leggyakoribb konfigurációs hibája, és szinte mindig öt konkrét ok valamelyikére vezethető vissza.
Az alábbiakban abban a sorrendben soroljuk fel őket, amelyben a leggyorsabban megtalálhatod a problémát.
1. A build időpontja és a futási idő két külön világ
Ez több ilyen hibát okoz, mint a másik négy ok együttvéve, és ezt értik meg a legnehezebben.
A szolgáltatáson beállított változók akkor léteznek, amikor a konténer fut. A Dockerfile-ban végrehajtott műveletek korábban, egy külön környezetben történnek. Egy RUN lépés nem látja a futási idejű változót, mert abban a pillanatban még nincs futási idő.
# 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"]
Ha valóban szükséged van egy értékre a build során, build argumentumként kell átadnod — ez azonban más mechanizmus, eltérő biztonsági tulajdonságokkal:
ARG BUILD_VERSION
RUN echo "Building $BUILD_VERSION"
Soha ne adj át így titkos értéket. A build argumentumok bekerülnek az image rétegeinek előzményeibe. Bárki, aki le tudja tölteni az image-et, el tudja olvasni őket.
2. A frontend változóit a rendszer beépíti, nem futás közben olvassa be
Ha a frontend production környezetben undefined értéket jelez, szinte biztosan ez az ok.
A böngészőnek nincs környezete. Amikor a import.meta.env.VITE_API_URL vagy a process.env.NEXT_PUBLIC_API_URL kifejezést írod, a bundler build időben behelyettesíti a konkrét szöveges értéket. A böngészőben nem történik keresés — az érték már bele lett fordítva.
Ez három következménnyel jár, amelyek gyakran okoznak meglepetést:
- A változó módosítása nem csinál semmit, amíg újra nem buildelsz. A régi érték benne van a JavaScript-fájlban.
- Az előtag kötelező. A Vite csak a
VITE_, a Next.js pedig csak aNEXT_PUBLIC_előtagú változókat teszi elérhetővé. Az előtag nélküli változókat szándékosan nem adja tovább. - Az így közzétett értékek nyilvánosak. Olyan fájlban találhatók, amelyet bárkinek kiszolgálsz. Soha ne tegyél titkos értéket
NEXT_PUBLIC_mögé, függetlenül attól, mit sugall az elnevezés.
Ezért nem konfigurálható egy előre elkészített image utólag ezen a módon. Ha az image-et máshol építették, és az értékeket már belefordították, akkor a szolgáltatáson beállított változók módosítása nem változtat semmin — a szövegek már benne vannak a bundle-ben.
3. Idézőjelek használata
A speciális karaktereket tartalmazó értékek könnyen módosulnak vagy csonkolódnak, ami egyértelmű hiba helyett zavarba ejtő hibaüzenetekhez vezet.
# 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
Ilyen problémát okozhat a # (komment), a $ (kibontás), a szóköz (argumentumokra bontás), a ! (interaktív bash esetén a history expansion) és az újsor — ez utóbbi pontosan egy gyakori esetben fordul elő: a privát kulcsoknál.
A többsoros értékek okozzák a legtöbb gondot. Ha egy PEM-kulcsot egy egysoros mezőbe illesztesz be, az újsorok eltűnnek, és olyan parse-hiba keletkezik, amely semmit nem árul el az újsorokról. Kódold Base64 formátumba, majd dekódold az alkalmazásban:
dockup env set "PRIVATE_KEY_B64=$(base64 -i key.pem)" my-project/my-api
4. Nem indítottad újra
A környezeti változókat a folyamat induláskor olvassa be. A módosítások a következő folyamatra vannak hatással, nem az éppen futóra.
A legtöbb platform automatikus újratelepítéssel kezeli ezt, amikor módosul a konfiguráció, de nem mindegyik. Részleges módosítás esetén pedig — például ha beállítasz három változót, újratelepítesz, majd beállítasz egy negyediket — az egyik változó kimarad.
dockup env list my-project/my-api --json # what is configured
dockup restart my-project/my-api # make the process re-read it
Az ellenőrzés, amely eldönti a kérdést: a változót a futó konténerből olvasd ki, ne a dashboardról.
dockup exec "printenv | sort" my-project/my-api
Ha szerepel a kimenetben, az alkalmazásod mégis undefined értéket jelez, akkor a probléma a kódodban van. Ha nem szerepel a kimenetben, akkor a konfigurációval van gond. Ez az egyetlen parancs két részre osztja a lehetséges okok körét.
5. Nem megfelelő hatókör
A változók általában egy szolgáltatáshoz, környezethez vagy projekthez vannak kötve. A production környezetben beállított változó nem látható egy preview környezetben. Ugyanígy az egyik szolgáltatáson beállított változó sem látható egy másik, ugyanahhoz a projekthez tartozó szolgáltatáson.
Ez a leggyakoribb oka annak, amikor valami az egyik helyen működik, a másikon viszont nem, miközben a kód azonos.
A hibakeresés sorrendje
# 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
Mindig az 1. lépéssel kezdd. Egy homályos problémát két egyértelmű probléma egyikévé alakít.
Kifejezetten a titkos értékekről
Platformtól függetlenül érdemes két szokást kialakítani.
Jelöld a titkos értékeket titkosként. A Dockupon a titkosként megjelölt változók maszkolva jelennek meg a listákban és az API-válaszokban — a dockup env list az érték helyett ******** karaktereket jelenít meg. Ez fontosabb, mint elsőre gondolnád, mert egy hitelesítő adat leggyakrabban nem támadás miatt szivárog ki, hanem egy képernyőképen, support ticketben vagy naplósorban.
Tartsd őket távol a build argumentumoktól és a frontend bundle-öktől. Mindkettőt el tudja olvasni bárki, aki hozzájut az artefaktumhoz. Ökölszabályként: ha egy általad terjesztett fájlba kerül, többé nem titkos érték.
Gyakran ismételt kérdések
Miért undefined a környezeti változóm build időben? Mert a build és a futási idő két külön környezet. A futási idejű változók nem léteznek az image buildelése közben. Ha valóban szükséged van egy értékre a build során, használj build argumentumot — titkos értéket azonban soha.
Miért nem látja a frontend a változót?
A bundlerek build időben behelyettesítik az értéket, és csak az előtaggal rendelkező neveket teszik elérhetővé — VITE_, NEXT_PUBLIC_. A változó módosítása új buildet igényel, és minden így közzétett érték nyilvánosan olvasható.
Újra kell indítanom a szolgáltatást egy változó módosítása után?
Igen. A futó folyamat már beolvasta a környezetét. A legtöbb platform automatikusan újratelepít módosításkor; ezt azonban a dashboard helyett a konténerben futtatott printenv paranccsal ellenőrizd.
Hogyan adhatok át többsoros értéket, például egy privát kulcsot? Kódold Base64 formátumba, állítsd be a kódolt szöveget, majd dekódold az alkalmazásban. Az egysoros környezeti változómezők eltávolítják az újsorokat, és olyan parse-hibákat okoznak, amelyek nem említik az újsorokat.
