SSD Nodes Learn Hosting plans →
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-10-25

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 yanayoitwa faili ya env

Docker Compose ina mifumo mitatu tofauti yenye majina yanayochanganya. Faili ya .env hujaza viwakilishi vya ${VARIABLE} ndani ya compose.yaml yenyewe, baada ya Compose kusoma YAML na kabla ya kuhakiki au kuendesha chochote. 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. Hivi havibadilishani, na pale viwili vinapoweka ufunguo mmoja, mshindi hupangwa na utaratibu wa kipaumbele uliowekwa kwenye nyaraka.

Mwongozo huu unaonyesha kila moja ikifanya kazi, unathibitisha kipaumbele kwa amri unayoweza kuendesha, kisha unashughulikia sehemu muhimu zaidi: vigezo vya mazingira (environment variables) vinaweza kusomwa na yeyote anayeweza kuendesha docker inspect, kwa hivyo nywila hazipaswi kuwekwa humo. Ikiwa wewe ni mgeni kwenye 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 faili la compose, si kwa ajili ya container

Unda saraka na uweke faili mbili ndani yake.

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

Sasa iulize Compose kile ilichokichakata kikweli.

docker compose config

Matokeo yanaonyesha image: alpine:3.20. Kishika nafasi kimeondoka, kwa sababu interpolation ilitokea wakati Compose ilipopakia faili. Compose hutafuta .env katika saraka ya mradi: saraka iliyotolewa na --project-directory ukiweka, vinginevyo saraka ya faili la kwanza lililopitishwa na -f, au saraka yako ya sasa. Inabadilisha kishika nafasi cha ${NAME} inachokipata katika thamani za YAML. Funguo hazifanyiwi interpolation kamwe, na $$ iliyomarishwa huzalisha alama ya dola halisi badala ya ubadilishaji.

Kisha endesha huduma.

docker compose run --rm demo

printenv ALPINE_TAG inatoka na status 1 na haichapishi chochote. Variable hiyo haipo ndani ya container. Huo ndio kutoelewana kwa kawaida zaidi: .env ilisanidi faili la compose, si mchakato (process). Faili la .env lenye POSTGRES_PASSWORD=hunter2 ndani yake halifanyi chochote kwa database yako isipokuwa kama sehemu fulani ya faili la compose inalirejelea.

${NAME:-default} hutoa thamani mbadala (fallback) wakati variable haijawekwa au haina kitu. ${NAME:?message} huifanya Compose kukataa kuanza na kuchapisha ujumbe wako, ambayo ndiyo chaguo sahihi kwa thamani isiyo na 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.env
services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
docker compose run --rm demo

Hii huchapisha from_env_file. Umbizo la faili ni mistari ya KEY=value ya kawaida, mstari mmoja kwa kila kigezo, huku # ikianzisha maoni (comment). Hii si shell, ingawa Compose huichakata kwa kutumia sheria chache zinazofanana na shell. Alama za kunukuu (quotes) za nje huondolewa, kwa hivyo KEY="value" na KEY=value hutoa matokeo sawa. Thamani zilizowekwa kwenye alama za kunukuu mbili (double-quoted) na zile zisizo na alama hupokea uingizaji wa placeholders za ${...}, wakati thamani zilizowekwa kwenye alama za kunukuu moja (single-quoted) hutumika kama zilivyo. Kiambishi awali cha export kinakubalika lakini hakihitajiki. Nafasi (spaces) zinazozunguka alama ya = huondolewa. Jambo la kuzingatia ni maoni ya ndani ya mstari: katika thamani isiyo na alama za kunukuu, nafasi ikifuatiwa na # huanzisha maoni, kwa hivyo weka alama za kunukuu kwenye thamani yoyote inayohusisha #.

Njia ya env_file isiyopatikana husababisha hitilafu na Compose husimama. Iweke kama ya hiari (optional) ikiwa faili inaweza kukosekana kihalali:

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

mazingira huweka vigezo (variables) ndani ya mstari

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

Sintaksia mbili zinakubalika, fomu ya ramani (mapping) hapo juu na fomu ya orodha inayotumia - GREETING=from_environment. Zinafanya kazi kwa namna moja. Zote zinashiriki mbinu moja ya ziada: ufunguo (key) usio na thamani hupitisha kigezo kutoka kwenye shell uliyotumia kuendesha docker compose. Katika fomu ya orodha, hii ni - GREETING tupu, na katika fomu ya ramani ni GREETING: bila kitu chochote baada ya koloni.

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

Hiyo huchapisha from_my_shell. Iendeshe bila kuweka GREETING kwenye shell na Compose haitaweka chochote, bila kutoa onyo. Kushindwa kwa upitishaji (pass-through) kimya kimya ni jambo la kufahamu, kwa sababu huduma inayozinduka ikiwa na kigezo cha nenosiri tupu mara nyingi huanza kwa mafanikio na inakuwa 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_environment
docker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETING

Ya 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, na ndivyo inavyojikuta ikinakiliwa kwenye majukwaa ya usaidizi. Michakato tanzu (child processes) hurithi kigezo hiki kwa chaguo-msingi, isipokuwa mzazi akianzisha michakato hiyo kwa makusudi na mazingira mbadala, na mchakato unaoendeshwa kama mtumiaji yuleyule wa PID 1, au unaoshikilia CAP_SYS_PTRACE, unaweza kukisoma kutoka /proc/1/environ. Katika container ambapo kila kitu kinaendeshwa kama root, huo ni kila mchakato. Programu inayoendeshwa kama mtumiaji asiye na upendeleo (unprivileged user) wakati PID 1 inaendeshwa kama root hupata kosa la ruhusa (permission error) kwenye faili hilo, ingawa bado inashikilia kigezo hicho katika mazingira yake yenyewe. Na vishughulikiaji vya ajali za programu (crash handlers) mara nyingi hutupa mazingira yote kwenye logi au ripoti ya hitilafu.

Uanachama wa kundi la docker kimsingi ni root kwenye host, kwa hivyo huu si mpaka wa upendeleo unaoweza kuutegemea. Mwongozo kuhusu akaunti za watumiaji wenye upendeleo mdogo kwenye VPS unaeleza kwa nini kundi hilo linastahili kuzuiliwa kwenye mashine 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.txt

Secret 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_PASSWORD

Amri 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.txt

Njia 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.env

install -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 config

Faili 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 placeholders za ${NAME} kwenye faili la compose, na linaweza pia kuweka vigezo vya Compose vyenyewe kama vile COMPOSE_PROJECT_NAME au COMPOSE_FILE. Halijawahi kuweka vigezo 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 unaweka 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 umewekwa katika sehemu zote mbili, thamani iliyo katika env_file haitatumika bila kutoa onyo.

Ninawezaje kuona thamani ya mwisho ambayo Compose itatumia?

Tekeleza docker compose config ili kuchapisha faili kamili la compose lililofanyiwa interpolation yote. Kwa container ambayo tayari inaendeshwa, docker inspect <container> --format '{{json .Config.Env}}' inaonyesha hasa kile ambacho mchakato wake umepokea.

Je, siri za Compose (secrets) zimesimbwa kwa njia fiche?

Hapana. Siri inayotegemea faili huwekwa (mount) ndani ya container kama faili la kawaida katika /run/secrets/<name>, na faili chanzo hukaa kwenye diski ya host bila kusimbwa. Faida yake ni upeo (scope), si usimbaji: thamani hiyo hubaki nje ya mazingira ya container, nje ya matokeo ya docker inspect, na nje ya crash dumps zinazochapisha mazingira.

Je, ninaweza kutumia alama za kunukuu na nafasi (spaces) katika faili la env?

Ndiyo. Compose huondoa alama za kunukuu zilizozunguka thamani, kwa hivyo KEY="value with spaces" na KEY=value with spaces zote hutoa value with spaces. Tumia alama za kunukuu moja (single quotes) wakati thamani ina $ ambayo haipaswi kufanyiwa interpolation, na weka alama za kunukuu kwa thamani yoyote iliyo na #, kwa sababu ikiwa haijawekwa alama hizo, itaanza maoni (comment). Nafasi zinazozunguka = huondolewa, kwa hivyo KEY = value bado huweka KEY.

Je, makala hii ilikusaidia?