Docker Compose मधील .env, env_file आणि secrets
Docker Compose मधील .env, env_file आणि environment यांतील फरक जाणून घ्या. कोणती value जिंकते, precedence कसे ठरते आणि passwords secrets मध्ये का ठेवावेत हे समजून घ्या.
env file म्हणून ओळखल्या जाणाऱ्या तीन गोष्टी
Docker Compose मध्ये सारखीच वाटणारी नावे असलेल्या तीन स्वतंत्र यंत्रणा आहेत. .env फाइलचा वापर compose.yaml मधील ${VARIABLE} प्लेसहोल्डरची मूल्ये भरण्यासाठी केला जातो. हे Compose ने फाइलचे विश्लेषण करण्यापूर्वीच होते. env_file: attribute key/value जोड्यांची फाइल कंटेनरच्या environment मध्ये लोड करते. environment: attribute compose फाइलमध्ये लिहिलेली variables थेट कंटेनरवर सेट करते. या यंत्रणा परस्पर अदलाबदल करता येत नाहीत. त्यांपैकी दोन यंत्रणांनी एकच key सेट केल्यास, जिंकणारी value दस्तऐवजीकरणात दिलेल्या precedence क्रमाने निश्चित होते.
या मार्गदर्शकात प्रत्येक यंत्रणा प्रत्यक्ष कशी कार्य करते ते दाखवले आहे. चालवता येणाऱ्या command द्वारे precedence सिद्ध केला आहे. त्यानंतर अधिक महत्त्वाचा मुद्दा स्पष्ट केला आहे: docker inspect चालवू शकणाऱ्या कोणत्याही व्यक्तीला environment variables वाचता येतात. त्यामुळे passwords त्यात ठेवू नयेत. compose files विषयी तुम्ही नवीन असाल, तर VPS वरील Docker Compose ची मूलभूत माहिती पासून सुरुवात करा आणि configuration साठी येथे परत या.
.env फाइल compose फाइलसाठी आहे, कंटेनरसाठी नाही
एक निर्देशिका तयार करा आणि त्यात दोन फाइल ठेवा.
mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .envservices:
demo:
image: alpine:${ALPINE_TAG}
command: printenv ALPINE_TAGआता Compose ने प्रत्यक्षात काय पार्स केले ते पाहा.
docker compose configआउटपुटमध्ये image: alpine:3.20 दिसते. प्लेसहोल्डर नाहीसा झाला आहे, कारण इंटरपोलेशन पार्स करतानाच झाले. Compose प्रोजेक्ट निर्देशिकेत .env शोधते. हीच compose फाइल असलेली निर्देशिका आहे. तेथे सापडणाऱ्या प्रत्येक ${NAME} ची जागा Compose संबंधित मूल्याने भरते.
आता सेवा सुरू करा.
docker compose run --rm demoprintenv ALPINE_TAG status 1 सह बंद होते आणि काहीही प्रिंट करत नाही. हे चल कंटेनरमध्ये अस्तित्वात नाही. हाच सर्वात सामान्य गैरसमज आहे: .env ने compose फाइल कॉन्फिगर केली, प्रक्रियेला नाही. POSTGRES_PASSWORD=hunter2 असलेली .env फाइल डेटाबेससाठी काहीही करत नाही, जोपर्यंत compose फाइलचा एखादा भाग तिचा संदर्भ घेत नाही.
चल unset किंवा रिक्त असल्यास ${NAME:-default} पर्यायी मूल्य देते. ${NAME:?message} मुळे Compose सुरू होण्यास नकार देते आणि तुमचा संदेश प्रिंट करते. सुरक्षित 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 ओळींचे असते. प्रत्येक ओळीत एक variable असतो आणि # ने comment सुरू होते. हे shell स्वरूप नाही. बहुतांश प्रकरणांत अवतरणचिन्हे value चाच भाग म्हणून ठेवली जातात आणि export prefixes आवश्यक नसतात. = चिन्हाच्या भोवती spaces ठेवू नका. तसे केल्यास KEY = value value मध्ये सुरुवातीला space असलेला KEY नावाचा variable तयार करते.
env_file path आढळला नाही, तर ही त्रुटी असते आणि Compose थांबते. फाइल वैधरीत्या अनुपस्थित असू शकत असल्यास तिला optional म्हणून चिन्हांकित करा:
env_file:
- path: ./app.env
required: falseenvironment inline पद्धतीने variables सेट करते
services:
demo:
image: alpine:3.20
command: printenv GREETING
environment:
GREETING: from_environmentदोन syntax स्वीकारल्या जातात: वरील mapping form आणि - GREETING=from_environment वापरणारी list form. दोन्हींचे वर्तन समान असते. List form मध्ये आणखी एक सुविधा आहे: value नसलेली bare key तुम्ही docker compose चालवलेल्या shell मधून variable पुढे पाठवते.
environment:
- GREETINGGREETING=from_my_shell docker compose run --rm demoयामुळे from_my_shell छापले जाते. Shell मध्ये GREETING सेट न करता ते चालवल्यास Compose काहीही सेट करत नाही आणि कोणतीही warning दाखवत नाही. अशा मूक pass-through failures ची माहिती असणे महत्त्वाचे आहे, कारण रिकाम्या password variable सह सुरू होणारी service अनेकदा यशस्वीपणे सुरू होते आणि प्रत्यक्षात पूर्णपणे उघडी राहते.
कोणते प्राधान्य मिळवते
Docker प्राधान्यक्रम दस्तऐवजीकरणात सर्वाधिक प्राधान्यापासून दिला आहे: कमांड लाइनवरील docker compose run -e, त्यानंतर shell किंवा env file मधून मूल्याचे interpolation होणारे 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पहिल्या command मधून from_environment प्रदर्शित होते. याचा अर्थ environment: ने app.env मधील मूल्यावर अधिलिखित केले. दुसऱ्या command मधून from_cli प्रदर्शित होते. compose file मधील कोणतीही गोष्ट कमांड लाइनवरील मूल्यावर अधिलिखित करत नाही.
तुमच्या 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" साध्या मजकुरात दिसते. आणखी तीन paths हेच मूल्य उघड करतात. docker compose config ते terminal वर प्रदर्शित करते. त्यामुळे ते support forum मध्ये paste केले जाऊ शकते. कंटेनरमधील कोणतीही process /proc/1/environ वाचू शकते आणि प्रत्येक child process ला हा variable वारशाने मिळतो. Application crash handlers संपूर्ण environment log किंवा error report मध्ये dump करतात.
docker गटाचे सदस्यत्व host वर root खात्यासारखेच प्रभावी असते. त्यामुळे या गटाला privilege boundary समजून त्यावर अवलंबून राहता येत नाही. VPS वरील किमान विशेषाधिकार असलेली वापरकर्ता खाती या मार्गदर्शकात shared box वर हा गट प्रतिबंधित ठेवणे का योग्य आहे हे स्पष्ट केले आहे.
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 ही Docker Official Images मध्ये वापरली जाणारी पद्धत आहे. यामध्ये postgres, mysql आणि mariadb यांचा समावेश होतो. त्यांच्या entrypoint scripts VARNAME_FILE तपासतात, फाइल वाचतात आणि तिच्या मजकुराचा वापर करतात. हे Docker चे feature नाही. त्यामुळे image मध्ये त्याची अंमलबजावणी असल्यासच ते कार्य करते. SOMETHING_FILE ग्राह्य धरले जाईल असे गृहीत धरण्यापूर्वी image चे documentation तपासा. याला समर्थन नसलेले applications बहुतेकदा startup वेळी फाइल स्वतः वाचू शकतात. किंवा तुम्ही path पास करू शकता आणि तुमच्या entrypoint कडून तो वापरू शकता.
चालू container मधून पडताळणी करा:
docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORDपहिला command password दाखवतो. दुसरा काहीही दाखवत नाही, कारण मूल्य environment मध्ये कधीच गेले नाही. हाच मुख्य उद्देश आहे: या container मधील docker inspect मध्ये फक्त निरुपद्रवी path दिसतो.
Host वरील source file सुरक्षित ठेवा, कारण secret ची गोपनीयता त्यामागील फाइलइतकीच असते:
chmod 600 db_password.txtVPS वरील व्यावहारिक मध्यम मार्ग
अनेक self hosted images _FILE variables ला समर्थन देत नाहीत. त्यामुळे environment variables वापरणे हाच एकमेव मार्ग असतो. एकाच administrator कडून व्यवस्थापित होणाऱ्या VPS वर वास्तववादी उद्दिष्ट असे आहे की तुमच्या project directory मधील सर्व वापरकर्त्यांना वाचता येणाऱ्या file मध्ये values साठून राहू नयेत आणि त्या 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 कडे असते. त्यामुळे त्या मशीनवरील non root user ती वाचू शकत नाही. मात्र docker चालवू शकणारी व्यक्ती container मधून value वाचू शकते. *.env आणि .env .gitignore मध्ये जोडा आणि त्याऐवजी key names व रिकाम्या values असलेली app.env.example commit करा. Commit केलेला password बदलणे आवश्यक असते.
Value बदलण्यासाठी service पुन्हा सुरू करावी लागते. Container process सुरू होताना environment variables एकदाच वाचले जातात. त्यामुळे file संपादित केल्यावर docker compose up -d --force-recreate db चालवेपर्यंत कोणताही बदल लागू होत नाही. VPS वर HTTPS मागे n8n या मार्गदर्शकातही हीच पद्धत वापरली आहे. तेथे encryption key compose file च्या बाहेर ठेवली आहे.
प्रत्येक वातावरणासाठी कॉन्फिगरेशन विभाजित करणे
Compose प्रकल्प निर्देशिकेतून डीफॉल्टनुसार .env वाचते. --env-file वापरून ते दुसऱ्या ठिकाणी निर्देशित करा.
docker compose --env-file .env.staging configएकापेक्षा अधिक फाइल्स क्रमाने वाचल्या जातात आणि नंतरच्या फाइल्स आधीच्या फाइल्समधील मूल्ये अधिलिखित करतात. गुप्त नसलेली डीफॉल्ट मूल्ये commit केलेल्या फाइलमध्ये ठेवा आणि secrets अशा फाइलमध्ये ठेवा जी कधीही serverच्या बाहेर जाणार नाही. हेच env_file: साठीही लागू होते; एकाच keyची पुनरावृत्ती असल्यास यादीतील शेवटची फाइल लागू होते.
FAQ
माझी .env फाइल कंटेनरमध्ये दुर्लक्षित का केली जाते?
ती दुर्लक्षित केलेली नाही. .env फाइल compose फाइलमधील ${NAME} प्लेसहोल्डरची केवळ अदलाबदल करते. ती कंटेनरमधील व्हेरिएबल्स कधीही सेट करत नाही. कंटेनरमध्ये मूल्य पाठवण्यासाठी त्याचा संदर्भ द्या: environment: { KEY: "${NAME}" }, किंवा त्याऐवजी env_file: ./that-file.env वापरा.
environment env_file वर प्राधान्य देते की उलट?
environment: चे प्राधान्य असते. Docker च्या दस्तऐवजीकरणानुसार environment अॅट्रिब्यूटला env_file अॅट्रिब्यूटपेक्षा अधिक प्राधान्य असते. कमांड लाइनवरील docker compose run -e या दोन्हींपेक्षा अधिक प्राधान्याचे असते. एखादी key दोन्ही ठिकाणी सेट असल्यास env_file मधील मूल्य शांतपणे वापरले जात नाही.
Compose वापरणार असलेले अंतिम मूल्य कसे पाहू?
सर्व interpolation लागू केलेली पूर्णपणे निराकरण केलेली compose फाइल छापण्यासाठी docker compose config चालवा. आधीपासून चालू असलेल्या कंटेनरसाठी, त्याच्या प्रक्रियेला नेमके कोणते मूल्य मिळाले हे docker inspect <container> --format '{{json .Config.Env}}' दाखवते.
Compose secrets एन्क्रिप्ट केलेले असतात का?
नाही. फाइल-आधारित secret कंटेनरमध्ये /run/secrets/<name> येथे साधी फाइल म्हणून mount केले जाते आणि source फाइल host च्या डिस्कवर unencrypted अवस्थेत राहते. याचा लाभ encryption नसून scope आहे: हे मूल्य कंटेनर environment मधून, docker inspect output मधून आणि environment छापणाऱ्या crash dumps मधून बाहेर राहते.
env फाइलमध्ये quotes आणि spaces वापरू शकतो का?
KEY=value with spaces वापरा आणि quotes वगळा. Compose ओळीचा उर्वरित संपूर्ण भाग मूल्य म्हणून मानते. त्यामुळे quotes बहुतेक वेळा मूल्यामध्ये literal characters म्हणून समाविष्ट होतात. = भोवती spaces कधीही ठेवू नका. तसे केल्यास key च्या शेवटी space येतो आणि कोणतेही मूल्य त्याच्याशी जुळत नाही.