Tofauti ya .env, env_file na environment katika Docker
Docker Compose hutumia .env, env_file na environment kwa njia tofauti. Jifunze kipaumbele chake na kwa nini hupaswi kuweka nywila kwenye faili hizi bali utumie Docker secrets.
Mambo matatu ambayo watu huita faili ya env
Docker Compose ina mifumo mitatu tofauti yenye majina yanayofanana na yanayochanganya. Faili ya .env hujaza viwakilishi vya ${VARIABLE} ndani ya compose.yaml yenyewe, kabla hata Compose haijachambua faili hiyo. Sifa ya env_file: hupakia faili ya jozi za ufunguo/thamani (key/value) kwenye mazingira ya container. Sifa ya environment: huweka vigezo (variables) kwenye container moja kwa moja, vilivyoandikwa ndani ya faili ya compose. Hayabadilishani, na wakati mawili kati yao yanapoweka ufunguo mmoja, mshindi hupangwa na utaratibu wa kipaumbele uliowekwa kwenye nyaraka.
Mwongozo huu unaonyesha kila moja ikifanya kazi, unathibitisha kipaumbele kwa amri unayoweza kuiendesha, kisha unashughulikia sehemu muhimu zaidi: vigezo vya mazingira vinaweza kusomwa na mtu yeyote anayeweza kuendesha docker inspect, kwa hivyo nywila hazipaswi kuwekwa humo. Ikiwa wewe ni mgeni katika faili za compose kwa ujumla, anza na Misingi ya Docker Compose kwenye VPS kisha urudi hapa kwa ajili ya usanidi.
Faili la .env ni kwa ajili ya compose file, si kwa ajili ya container
Tengeneza saraka (directory) na uweke faili mbili ndani yake.
mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .envservices:
demo:
image: alpine:${ALPINE_TAG}
command: printenv ALPINE_TAGSasa iulize Compose kile ilichokichakata (parse).
docker compose configMatokeo yanaonyesha image: alpine:3.20. Kishika nafasi (placeholder) kimeondoka, kwa sababu interpolation ilitokea wakati wa kuchakata. Compose hutafuta .env katika saraka ya mradi, ambayo ndiyo saraka iliyoshikilia compose file, na kubadilisha kila ${NAME} inachokipata.
Kisha endesha huduma hiyo.
docker compose run --rm demoprintenv ALPINE_TAG inatoka (exit) ikiwa na hali ya 1 na haichapishi chochote. Variable hiyo haipo ndani ya container. Hilo ndilo kosa la kawaida zaidi la kutoelewana: .env ilisanidi compose file, si mchakato (process). Faili la .env lenye POSTGRES_PASSWORD=hunter2 ndani yake halifanyi chochote kwa database yako isipokuwa kama sehemu fulani ya compose file inalirejelea.
${NAME:-default} hutoa thamani mbadala (fallback) wakati variable haijawekwa au ni tupu. ${NAME:?message} huifanya Compose kugoma kuanza na kuchapisha ujumbe wako, ambayo ndiyo chaguo sahihi kwa thamani ambayo haina thamani chaguo-msingi (default) salama.
env_file hupakia vigezo kwenye container
Sifa ya env_file: hutaja faili moja au zaidi ambazo maudhui yake huwa vigezo vya mazingira (environment variables) vya container.
printf 'GREETING=from_env_file\nAPP_MODE=production\n' > app.envservices:
demo:
image: alpine:3.20
command: printenv GREETING
env_file:
- ./app.envdocker compose run --rm demoHii huchapisha from_env_file. Umbizo la faili ni mistari ya KEY=value ya kawaida, moja kwa kila mstari, huku # ikianzisha maoni (comment). Hii si shell. Alama za kunukuu (quotes) huhifadhiwa kama sehemu ya thamani katika hali nyingi, na viambishi vya export havihitajiki. Usiweke nafasi (spaces) kuzunguka alama ya =, kwa sababu KEY = value hutengeneza kigezo chenye jina halisi la KEY chenye nafasi ya ziada mwanzoni mwa thamani yake.
Njia ya env_file isiyopatikana ni kosa na Compose husimama. Iweke kama ya hiari (optional) ikiwa faili inaweza kukosekana kihalali:
env_file:
- path: ./app.env
required: falsemazingira huweka vigezo (variables) ndani ya mstari
services:
demo:
image: alpine:3.20
command: printenv GREETING
environment:
GREETING: from_environmentSintaksia mbili zinakubalika, fomu ya ramani (mapping) hapo juu na fomu ya orodha inayotumia - GREETING=from_environment. Zinafanya kazi kwa njia sawa. Fomu ya orodha ina ujanja mmoja wa ziada: ufunguo (key) tupu bila thamani hupitisha kigezo kutoka kwenye shell uliyotumia kuendesha docker compose.
environment:
- GREETINGGREETING=from_my_shell docker compose run --rm demoHiyo huchapisha from_my_shell. Iendeshe bila kuweka GREETING kwenye shell na Compose haitaweka chochote, bila kutoa onyo. Kushindwa kupitisha vigezo kimyakimya ni jambo la kufahamu, kwa sababu huduma inayozinduka ikiwa na kigezo cha nenosiri tupu mara nyingi huanza kwa mafanikio na kubaki wazi kabisa.
Ni ipi inayoshinda
Docker inaelezea utaratibu wa kipaumbele, kuanzia ya juu zaidi: docker compose run -e kwenye mstari wa amri (command line), ikifuatiwa na environment au env_file ambazo thamani yake huchukuliwa kutoka kwenye shell yako au faili ya env, kisha environment ya kawaida kwenye faili ya compose, ikifuatiwa na env_file, na mwisho ni maelekezo ya ENV yaliyowekwa ndani ya image yenyewe.
Muhtasari wa kazi za kila siku: environment: inashinda env_file:, na -e kwenye mstari wa amri inashinda zote mbili. Thibitisha hili kwa faili moja.
services:
demo:
image: alpine:3.20
command: printenv GREETING
env_file:
- ./app.env
environment:
GREETING: from_environmentdocker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETINGYa kwanza inachapisha from_environment, kwa hivyo environment: ilibatilisha thamani iliyokuwa kwenye app.env. Ya pili inachapisha from_cli. Hakuna kitu kwenye faili ya compose kinachoweza kubatilisha mstari wa amri.
Wakati container inafanya kazi kana kwamba usanidi wako haukutumika, usikisie. docker compose config inachapisha faili iliyokamilika baada ya kutatua kila kitu, na docker compose config --environment inachapisha vigezo vya interpolation ambavyo Compose inatumia. Ripoti nyingi za "faili yangu ya env imepuuzwa" mara nyingi hutokana na thamani kuwekwa mara mbili katika viwango tofauti.
Kwa nini vigezo vya mazingira (environment variables) huvuja
Weka nenosiri katika environment: na litahifadhiwa kwenye usanidi wa container kwenye diski, likiwa linaonekana na mtumiaji yeyote aliye katika kundi la docker.
docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'Matokeo yana "DB_PASSWORD=hunter2" katika maandishi ya kawaida (plain text). Njia nyingine tatu hufichua thamani hiyo hiyo. docker compose config huchapisha thamani hiyo kwenye terminal, jambo ambalo ndilo husababisha thamani hiyo kubandikwa kwenye majukwaa ya usaidizi. Mchakato wowote ndani ya container unaweza kusoma /proc/1/environ na kila mchakato mwana (child process) hurithi kigezo hicho. Vilevile, vishughulikiaji vya hitilafu (crash handlers) vya programu mara nyingi hutoa mazingira yote kwenye logi au ripoti ya hitilafu.
Uanachama wa kundi la docker ni sawa na kuwa na mamlaka ya root kwenye seva pangishi (host), kwa hivyo huu si mpaka wa upendeleo unaoweza kuutegemea. Mwongozo kuhusu akaunti za watumiaji zenye upendeleo mdogo kwenye VPS unaeleza kwa nini kundi hilo linapaswa kudhibitiwa kwenye seva yoyote inayoshirikiwa.
Compose secrets huweka thamani kwenye faili
Compose inasaidia secrets zinazotegemea faili. Thamani hiyo huwekwa ndani ya container kama faili badala ya kuingizwa kwenye environment.
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txtSecret hiyo huwekwa kwenye /run/secrets/db_password ndani ya container. Jina lililo baada ya slash ni jina la secret kutoka kwenye block ya kiwango cha juu ya secrets:.
Sufiksi ya _FILE ni utaratibu unaotumiwa na Docker Official Images, ikiwemo postgres, mysql na mariadb. Script hizo za entrypoint hukagua VARNAME_FILE, husoma faili hilo, na kutumia yaliyomo. Hii si kipengele cha Docker, kwa hiyo inafanya kazi pale tu ambapo image husika imetekeleza utaratibu huo. Kagua nyaraka za image kabla ya kudhani kuwa SOMETHING_FILE itakubaliwa. Programu zisizosaidia utaratibu huu mara nyingi zinaweza kusoma faili hilo zenyewe wakati wa kuanza, au unaweza kupitisha njia (path) na kuruhusu entrypoint yako mwenyewe ifanye kazi hiyo.
Thibitisha kutoka ndani ya container inayofanya kazi:
docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORDAmri ya kwanza huchapisha nenosiri. Ya pili haichapishi chochote, kwa sababu thamani hiyo haikuwahi kuingia kwenye environment. Hilo ndilo lengo kuu: docker inspect kwenye container hii huonyesha njia isiyo na madhara pekee.
Linda faili la chanzo kwenye host, kwa sababu usiri wa secret unategemea usalama wa faili lililo nyuma yake:
chmod 600 db_password.txtNjia ya wastani ya kiutendaji kwenye VPS
Picha nyingi za self-hosted hazitumii vigezo vya _FILE, kwa hivyo environment variables ndiyo njia pekee ya kuingiza data. Kwenye VPS inayodhibitiwa na msimamizi mmoja, lengo la kweli ni kuzuia thamani hizo zisikae kwenye faili inayoweza kusomwa na kila mtu katika saraka ya mradi wako, na kuzizuia zisiingie kwenye 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.envinstall -m 600 hutengeneza faili hiyo ikiwa na mode iliyowekwa tayari, kwa hivyo hakuna muda ambao inaweza kusomwa na kila mtu. Root ndiye mmiliki, kwa hivyo mtumiaji asiye root kwenye seva hawezi kuisoma, ingawa yeyote anayeweza kuendesha docker bado anaweza kusoma thamani hiyo kutoka kwenye container. Ongeza *.env na .env kwenye .gitignore na uweke (commit) app.env.example iliyo na majina ya funguo (keys) yakiwa na thamani tupu badala yake. Nenosiri lililowekwa kwenye commit ni nenosiri lililofichuliwa (rotated).
Kubadilisha thamani (rotating) inamaanisha kuanzisha upya huduma. Environment variables husomwa mara moja wakati mchakato wa container unapoanza, kwa hivyo kuhariri faili hakubadilishi chochote hadi utakapokimbiza docker compose up -d --force-recreate db. Huu ni muundo uleule unaotumiwa katika mwongozo wa n8n nyuma ya HTTPS kwenye VPS, ambapo ufunguo wa usimbaji (encryption key) unakaa nje ya faili ya compose.
Kugawanya usanidi kulingana na mazingira
Compose husoma .env kutoka kwenye saraka ya mradi kwa chaguomsingi. Elekeza kwenye eneo lingine kwa kutumia --env-file.
docker compose --env-file .env.staging configFaili nyingi husomwa kwa mpangilio, na faili za baadaye hubatilisha zile za awali. Weka mipangilio ya kawaida isiyo ya siri kwenye faili inayohifadhiwa kwenye mfumo wa udhibiti wa matoleo (version control), na uweke siri kwenye faili ambayo haitoki kamwe kwenye seva. Hali hii inatumika pia kwa env_file:, ambapo faili ya mwisho iliyoorodheshwa ndiyo inayoshinda kwa funguo zinazojirudia.
FAQ
Kwa nini faili langu la .env linapuuzwa ndani ya container?
Halipuuzwi. Faili la .env hubadilisha tu viwakilishi vya ${NAME} vilivyo kwenye faili la compose. Halijawahi kuweka vigezo (variables) ndani ya container. Ili kupata thamani hiyo ndani ya container, iite kwa kutumia: environment: { KEY: "${NAME}" }, au tumia env_file: ./that-file.env badala yake.
Je, environment inabatilisha env_file, au kinyume chake?
environment: ndiyo inayoshinda. Mpangilio uliothibitishwa wa Docker huweka sifa ya environment juu ya sifa ya env_file, na zote mbili ziko chini ya docker compose run -e kwenye mstari wa amri. Ikiwa ufunguo (key) umewekwa katika sehemu zote mbili, thamani iliyo kwenye env_file haitatumika bila kutoa onyo.
Ninawezaje kuona thamani ya mwisho ambayo Compose itatumia?
Tekeleza docker compose config ili kuchapisha faili kamili la compose baada ya interpolation yote kutumika. Kwa container ambayo tayari inafanya kazi, docker inspect <container> --format '{{json .Config.Env}}' inaonyesha hasa kile ambacho mchakato wake umepokea.
Je, siri (secrets) za Compose zimesimbwa kwa njia fiche?
Hapana. Siri inayotegemea faili huwekwa (mount) ndani ya container kama faili la kawaida kwenye /run/secrets/<name>, na faili la chanzo hukaa kwenye diski ya mwenyeji (host) bila kusimbwa. Faida yake ni upeo wa matumizi (scope), si usimbaji: thamani hiyo hubaki nje ya mazingira ya container, nje ya matokeo ya docker inspect, na nje ya faili za crash dump zinazochapisha mazingira ya mfumo.
Je, ninaweza kutumia alama za kunukuu (quotes) na nafasi (spaces) kwenye faili la env?
Tumia KEY=value with spaces na uache alama za kunukuu. Compose huchukulia sehemu yote iliyobaki ya mstari kama thamani, kwa hivyo alama za kunukuu mara nyingi huishia kuwa herufi halisi ndani ya thamani hiyo. Usiweke kamwe nafasi kuzunguka =, kwa sababu ufunguo utabeba nafasi hiyo mwishoni na hakuna kitakacholingana nacho.