Docker Composeలో .env, env_file, environment తేడాలు
Docker Composeలో .env, env_file, environment ఎలా వేర్వేరుగా పనిచేస్తాయో, ఏ విలువకు ప్రాధాన్యం ఉంటుందో, passwords ను secrets లో ఎందుకు ఉంచాలో తెలుసుకోండి.
env file అని పిలిచే మూడు అంశాలు
Docker Compose లో పేర్లు దాదాపు ఒకేలా ఉండటం వల్ల గందరగోళం కలిగించే మూడు వేర్వేరు విధానాలు ఉన్నాయి. .env ఫైల్లోని విలువలు, Compose ఆ ఫైల్ను parse చేయడానికి ముందే, compose.yaml లోని ${VARIABLE} placeholders ను నింపుతాయి. env_file: attribute key/value జతల ఫైల్ను container environment లోకి లోడ్ చేస్తుంది. environment: attribute compose file లోనే రాసిన variables ను container పై నేరుగా సెట్ చేస్తుంది. ఇవి పరస్పరం మార్చుకునే అంశాలు కావు. వీటిలో రెండు ఒకే key ను సెట్ చేసినప్పుడు, ఏ విలువ గెలుస్తుందో documented precedence order నిర్ణయిస్తుంది.
ఈ guide లో ప్రతి విధానం ఎలా పనిచేస్తుందో చూపిస్తాం. మీరు అమలు చేయగల command తో precedence ను నిర్ధారిస్తాం. ఆ తర్వాత మరింత ముఖ్యమైన అంశాన్ని వివరిస్తాం: docker inspect అమలు చేయగల ఎవరైనా environment variables ను చదవగలరు. అందువల్ల passwords ను వాటిలో ఉంచకూడదు. మీరు compose files కు కొత్తవారైతే, ముందుగా VPSలో Docker Compose ప్రాథమికాలు చదివి, configuration కోసం ఇక్కడికి తిరిగి రండి.
.env ఫైల్ compose ఫైల్ కోసం, container కోసం కాదు
ఒక directoryని సృష్టించి, అందులో రెండు ఫైళ్లను ఉంచండి.
mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .envservices:
demo:
image: alpine:${ALPINE_TAG}
command: printenv ALPINE_TAGఇప్పుడు Compose నిజంగా ఏమి parse చేసిందో అడగండి.
docker compose configఅవుట్పుట్లో image: alpine:3.20 కనిపిస్తుంది. Placeholder తొలగిపోయింది, ఎందుకంటే interpolation parse సమయంలోనే జరిగింది. Compose project directoryలోని .env కోసం చూస్తుంది. ఇది compose ఫైల్ ఉన్న directory. అక్కడ కనిపించే ప్రతి ${NAME} స్థానంలో దాని విలువను ఉంచుతుంది.
తర్వాత serviceని అమలు చేయండి.
docker compose run --rm demoprintenv ALPINE_TAG status 1తో ముగిసి, ఏమీ print చేయదు. Containerలో ఆ variable ఉండదు. ఇదే అత్యంత సాధారణ అపార్థం: .env compose ఫైల్ను configure చేసింది, processను కాదు. POSTGRES_PASSWORD=hunter2 ఉన్న .env ఫైల్ను ఉంచడం మాత్రమే మీ database కోసం ఏమీ చేయదు. Compose ఫైల్లోని ఏదైనా భాగం దాన్ని reference చేసినప్పుడే అది ప్రభావం చూపుతుంది.
Variable unsetగా లేదా ఖాళీగా ఉన్నప్పుడు ${NAME:-default} fallback విలువను అందిస్తుంది. ${NAME:?message} Composeను ప్రారంభించకుండా నిరాకరించి, మీరు ఇచ్చిన messageను print చేస్తుంది. సురక్షితమైన default లేని విలువకు ఇదే సరైన ఎంపిక.
env_file కంటైనర్లోకి వేరియబుల్స్ను లోడ్ చేస్తుంది
env_file: attribute కంటైనర్ environment variablesగా మారే కంటెంట్ ఉన్న ఒకటి లేదా అంతకంటే ఎక్కువ ఫైళ్లను సూచిస్తుంది.
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 demoఇది from_env_file ను ప్రింట్ చేస్తుంది. ఫైల్ ఫార్మాట్ సాధారణ KEY=value లైన్లతో ఉంటుంది. ప్రతి లైన్లో ఒక వేరియబుల్ ఉంటుంది. # తో ప్రారంభమయ్యే లైన్ commentగా పరిగణించబడుతుంది. ఇది shell ఫైల్ కాదు. చాలా సందర్భాల్లో quotes valueలో భాగంగానే ఉంచబడతాయి. export prefixes అవసరం లేదు. = గుర్తు చుట్టూ ఖాళీలు పెట్టవద్దు. లేకపోతే KEY = value విలువగా, ప్రారంభంలో ఖాళీ ఉన్న KEY పేరుతో వేరియబుల్ సృష్టించబడుతుంది.
env_file path కనిపించకపోతే అది errorగా పరిగణించబడుతుంది మరియు Compose ఆగిపోతుంది. ఫైల్ లేకపోవడం సముచితమైన పరిస్థితి అయితే, దాన్ని optionalగా గుర్తించండి:
env_file:
- path: ./app.env
required: falseenvironment వేరియబుల్స్ను inlineగా సెట్ చేస్తుంది
services:
demo:
image: alpine:3.20
command: printenv GREETING
environment:
GREETING: from_environmentరెండు syntaxలు ఆమోదించబడతాయి: పై mapping రూపం మరియు - GREETING=from_environmentను ఉపయోగించే list రూపం. రెండూ ఒకే విధంగా పనిచేస్తాయి. list రూపంలో ఒక అదనపు సౌలభ్యం ఉంది: విలువ లేకుండా ఉన్న bare key, మీరు docker composeను అమలు చేసిన shell నుంచి ఆ వేరియబుల్ను అలాగే pass through చేస్తుంది.
environment:
- GREETINGGREETING=from_my_shell docker compose run --rm demoఅది from_my_shellను ముద్రిస్తుంది. shellలో GREETINGను సెట్ చేయకుండా దీన్ని అమలు చేస్తే, Compose ఏదీ సెట్ చేయదు మరియు ఎలాంటి హెచ్చరికను చూపదు. ఇలాంటి నిశ్శబ్ద pass-through వైఫల్యాలను తెలుసుకోవడం ముఖ్యం. ఎందుకంటే ఖాళీ password వేరియబుల్తో ప్రారంభమయ్యే service సాధారణంగా విజయవంతంగా ప్రారంభమవుతుంది, కానీ పూర్తిగా రక్షణ లేకుండా ఉంటుంది.
ఏది ప్రాధాన్యత పొందుతుంది
Docker ప్రాధాన్యత క్రమాన్ని అత్యధికం నుంచి తక్కువ వరకు ఇలా నిర్వచిస్తుంది: కమాండ్ లైన్లోని docker compose run -e, ఆ తర్వాత మీ shell లేదా env file నుంచి విలువను పొందే environment లేదా env_file, ఆ తర్వాత compose file లోని సాధారణ environment, ఆ తర్వాత env_file, చివరగా image లో ముందుగానే చేర్చిన ENV directive.
రోజువారీ పనికి సంక్షిప్తంగా: environment: కంటే env_file: ప్రాధాన్యత పొందుతుంది. కమాండ్ లైన్లోని -e రెండింటికంటే ప్రాధాన్యత పొందుతుంది. దీన్ని ఒకే fileలో నిరూపించండి.
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 GREETINGమొదటి కమాండ్ from_environment ను ముద్రిస్తుంది. అంటే environment:, app.env లోని విలువను భర్తీ చేసింది. రెండవ కమాండ్ from_cli ను ముద్రిస్తుంది. compose file లోని ఏదీ command line విలువను భర్తీ చేయదు.
మీ config వర్తించనట్లుగా container ప్రవర్తిస్తే, ఊహించవద్దు. docker compose config పూర్తిగా పరిష్కరించబడిన file ను ముద్రిస్తుంది. docker compose config --environment Compose ఉపయోగిస్తున్న interpolation variables ను ముద్రిస్తుంది. "నా env file పట్టించుకోలేదు" అనే చాలా నివేదికల్లో, రెండు వేర్వేరు స్థాయిల్లో ఒకే విలువ రెండుసార్లు సెట్ చేయబడి ఉంటుంది.
పర్యావరణ వేరియబుల్స్ ఎందుకు లీక్ అవుతాయి
environment:లో పాస్వర్డ్ను సెట్ చేస్తే, అది డిస్క్లోని కంటైనర్ కాన్ఫిగరేషన్లో నిల్వ అవుతుంది. docker గ్రూప్లోని ఏ యూజర్ అయినా దాన్ని చూడగలరు.
docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'అవుట్పుట్లో "DB_PASSWORD=hunter2" సాదా టెక్స్ట్గా ఉంటుంది. మరో మూడు పాత్లు కూడా అదే విలువను బహిర్గతం చేస్తాయి. docker compose config దాన్ని టెర్మినల్కు ప్రింట్ చేస్తుంది. అందువల్ల అది సపోర్ట్ ఫోరమ్లోకి పేస్ట్ అవుతుంది. కంటైనర్లోని ఏ ప్రాసెస్ అయినా /proc/1/environను చదవగలదు. ప్రతి చైల్డ్ ప్రాసెస్ ఆ వేరియబుల్ను వారసత్వంగా పొందుతుంది. అలాగే, అప్లికేషన్ క్రాష్ హ్యాండ్లర్లు సాధారణంగా మొత్తం పర్యావరణాన్ని లాగ్లోకి లేదా ఎర్రర్ రిపోర్ట్లోకి డంప్ చేస్తాయి.
docker గ్రూప్లో సభ్యత్వం హోస్ట్పై root యాక్సెస్తో సమానం. కాబట్టి దీనిని ఆధారపడదగిన ప్రివిలేజ్ సరిహద్దుగా పరిగణించకూడదు. VPSలో కనీస ప్రివిలేజ్ కలిగిన యూజర్ ఖాతాలు గురించిన గైడ్, షేర్డ్ సర్వర్లో ఆ గ్రూప్ సభ్యత్వాన్ని ఎందుకు పరిమితం చేయాలో వివరిస్తుంది.
Compose secrets విలువను ఒక ఫైల్లో ఉంచుతాయి
Compose ఫైల్ ఆధారిత secrets కు మద్దతు ఇస్తుంది. విలువను environment లోకి చేర్చకుండా, ఫైల్గా container లోకి mount చేస్తుంది.
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./db_password.txtsecret, container లోపల /run/secrets/db_password వద్ద mount అవుతుంది. slash తర్వాత ఉన్న పేరు, top-level secrets: block లోని secret పేరు.
_FILE suffix అనేది postgres, mysql మరియు mariadb సహా Docker Official Images ఉపయోగించే ఒక convention. ఆ entrypoint scripts VARNAME_FILE కోసం తనిఖీ చేసి, ఫైల్ను చదివి, దాని కంటెంట్ను ఉపయోగిస్తాయి. ఇది Docker feature కాదు. కాబట్టి image దీన్ని అమలు చేసినప్పుడు మాత్రమే పనిచేస్తుంది. SOMETHING_FILE గౌరవించబడుతుందని భావించే ముందు image documentation ను తనిఖీ చేయండి. దీనికి మద్దతు ఇవ్వని applications startup సమయంలో ఫైల్ను స్వయంగా చదవగలవు. లేదా path ను pass చేసి, మీ స్వంత entrypoint ద్వారా చదివించవచ్చు.
నడుస్తున్న container లోపల నుంచి ధృవీకరించండి:
docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORDమొదటి command password ను చూపిస్తుంది. రెండవది ఏమీ చూపించదు, ఎందుకంటే విలువ environment లోకి ప్రవేశించలేదు. ఇదే ముఖ్య ఉద్దేశ్యం: ఈ container పై docker inspect harmless path మాత్రమే చూపిస్తుంది.
Host పై source file కు తగిన రక్షణ కల్పించండి. ఎందుకంటే secret భద్రత, దాని వెనుక ఉన్న file భద్రతకు మాత్రమే సమానం:
chmod 600 db_password.txtVPSలో ఆచరణాత్మక మధ్యమార్గం
చాలా స్వయంగా నిర్వహించే images, _FILE variablesకు మద్దతు ఇవ్వవు. అందువల్ల ప్రవేశానికి environment variables మాత్రమే మార్గం. ఒకే administrator నిర్వహించే VPSలో వాస్తవిక లక్ష్యం, మీ project directoryలోని అందరికీ చదవగలిగే fileలో విలువలు ఉండకుండా చేయడం మరియు వాటిని 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 fileను ముందుగానే సరైన modeతో సృష్టిస్తుంది. అందువల్ల అది అందరికీ చదవగలిగే స్థితిలో ఉండే సమయం ఉండదు. దానికి root యజమాని కాబట్టి, ఆ systemలోని non root user దాన్ని చదవలేడు. అయితే docker అమలు చేయగల ఎవరైనా container నుంచి ఆ విలువను చదవగలరు. *.env మరియు .envలను .gitignoreకు జోడించండి. వాటి బదులుగా key namesతో, ఖాళీ విలువలతో ఉన్న app.env.exampleను commit చేయండి. Commit చేసిన passwordను rotate చేయాలి.
విలువను rotate చేయడం అంటే serviceను restart చేయడం. Container process ప్రారంభమైనప్పుడు environment variablesను ఒక్కసారి మాత్రమే చదువుతుంది. అందువల్ల fileను సవరించినా, మీరు docker compose up -d --force-recreate db అమలు చేసే వరకు ఎలాంటి మార్పు ఉండదు. ఇది VPSలో HTTPS వెనుక n8n guideలో ఉపయోగించిన అదే విధానం. అందులో encryption key compose file వెలుపల ఉంటుంది.
ప్రతి వాతావరణానికి విడిగా configuration
Compose డిఫాల్ట్గా project directory నుంచి .env ను చదువుతుంది. --env-file తో దాన్ని వేరే స్థానానికి సూచించండి.
docker compose --env-file .env.staging configబహుళ files క్రమంలో చదవబడతాయి. తర్వాతి files, ముందు files లోని విలువలను override చేస్తాయి. రహస్యంకాని default విలువలను committed file లో ఉంచండి. secrets ను server ను ఎప్పటికీ విడిచిపెట్టని file లో ఉంచండి. ఇదే env_file: కు కూడా వర్తిస్తుంది. ఒకే key పలుమార్లు ఉంటే, చివరగా జాబితా చేసిన file లోని విలువ అమలవుతుంది.
FAQ
నా .env ఫైల్ container లో ఎందుకు పరిగణించబడటం లేదు?
అది పరిగణించబడకుండా లేదు. .env ఫైల్ compose file లోని ${NAME} placeholders ను మాత్రమే భర్తీ చేస్తుంది. ఇది container లోని variables ను ఎప్పుడూ సెట్ చేయదు. విలువను container లోకి పంపడానికి దాన్ని reference చేయండి: environment: { KEY: "${NAME}" }, లేదా బదులుగా env_file: ./that-file.env ఉపయోగించండి.
environment, env_file ను override చేస్తుందా, లేదా దీనికి విరుద్ధంగా జరుగుతుందా?
environment: కు ప్రాధాన్యం ఉంటుంది. Docker documentation ప్రకారం, environment attribute కు env_file attribute కంటే ఎక్కువ ప్రాధాన్యం ఉంటుంది. ఇవి రెండూ command line లోని docker compose run -e కంటే తక్కువ ప్రాధాన్యం కలిగి ఉంటాయి. ఒక key రెండు చోట్లా సెట్ చేస్తే, env_file లోని విలువ ఎటువంటి సందేశం లేకుండా ఉపయోగించబడదు.
Compose ఉపయోగించే తుది విలువను ఎలా చూడాలి?
అన్ని interpolation వర్తింపజేసిన fully resolved compose file ను ముద్రించడానికి docker compose config అమలు చేయండి. ఇప్పటికే నడుస్తున్న container కోసం, దాని process కు అందిన విలువను docker inspect <container> --format '{{json .Config.Env}}' ఖచ్చితంగా చూపిస్తుంది.
Compose secrets encrypted గా ఉంటాయా?
లేదు. file based secret ను /run/secrets/<name> వద్ద plain file గా container లో mount చేస్తారు. source file కూడా host disk లో unencrypted గా ఉంటుంది. దీని ప్రయోజనం scope నియంత్రణ, encryption కాదు: ఆ విలువ container environment లోకి, docker inspect output లోకి, లేదా environment ను ముద్రించే crash dumps లోకి వెళ్లదు.
env file లో quotes మరియు spaces ఉపయోగించవచ్చా?
KEY=value with spaces ఉపయోగించి quotes ను వదిలేయండి. Compose line లో మిగిలిన మొత్తం భాగాన్ని value గా పరిగణిస్తుంది. అందువల్ల quotes సాధారణంగా value లో literal characters గా చేరతాయి. = చుట్టూ spaces ఎప్పుడూ పెట్టవద్దు. అలా చేస్తే key చివర trailing space చేరుతుంది, దానితో ఏదీ match కాదు.