मैं डॉकर कंटेनरों में पर्यावरण चर कैसे पार करूं?


826

मैं डॉकर के लिए नया हूं, और यह स्पष्ट नहीं है कि कंटेनर से बाहरी डेटाबेस तक कैसे पहुंचा जाए। कनेक्शन स्ट्रिंग में हार्ड-कोड का सबसे अच्छा तरीका है?

# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string

जवाबों:


1239

आप -eध्वज के साथ अपने कंटेनरों में पर्यावरण चर पास कर सकते हैं ।

स्टार्टअप स्क्रिप्ट से एक उदाहरण:

sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \ 
-e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \
-e POSTGRES_ENV_POSTGRES_USER='bar' \
-e POSTGRES_ENV_DB_NAME='mysite_staging' \
-e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \
-e SITE_URL='staging.mysite.com' \
-p 80:80 \
--link redis:redis \  
--name container_name dockerhub_id/image_name

या, यदि आप कमांड-लाइन पर मान नहीं रखना चाहते हैं जहां यह प्रदर्शित किया जाएगा ps , आदि, -eतो वर्तमान वातावरण से मूल्य में खींच सकते हैं यदि आप इसे बिना देते हैं =:

sudo PASSWORD='foo' docker run  [...] -e PASSWORD [...]

यदि आपके पास कई पर्यावरण चर हैं और विशेष रूप से यदि वे गुप्त होने के लिए हैं, तो आप एक एनवी-फाइल का उपयोग कर सकते हैं :

$ docker run --env-file ./env.list ubuntu bash

--Env- फाइल फ्लैग को एक तर्क के रूप में फाइलनाम लेता है और प्रत्येक लाइन को VAR = VAL फॉर्मेट में होने की उम्मीद करता है, जो तर्क --env को दिए गए की नकल करता है। टिप्पणी लाइनों को केवल # के साथ उपसर्ग करने की आवश्यकता है


क्या इसे करने का कोई आसान रास्ता है? यह वास्तव में हर बार विभिन्न चर के साथ कंटेनर को फिर से बनाने के लिए परेशान है। शायद इसे एक फ़ाइल में संग्रहीत करें?
1938 में जेसन एक्सलसन

29
मैं शेल स्क्रिप्ट्स में docker रन कमांड को स्टोर करता हूं, (./start_staging.sh आदि ..) तो उन्हें Ansible का उपयोग करके दूरस्थ रूप से निष्पादित करें।
इलता

1
मुझे काम करने के लिए दूसरा संस्करण प्राप्त करने में परेशानी हो रही है; मैंने पर्यावरण में PASSWORD = foo सेट किया है, फिर पासवैन PASSWORD, और केवल "PASSWORD" शब्द कंटेनर के config.json में दिखाई देता है; हर दूसरे पर्यावरण चर में एक कुंजी और एक मूल्य होता है। मैं डॉकर 1.12.1 का उपयोग कर रहा हूं।
केविन बर्क

@ केविनबर्के: मुझे लगता है कि आप चाहते हैं--PASSWORD = $ PASSWORD यदि आप वर्तमान शेल वातावरण से पढ़ रहे हैं
इरेटा

8
@ केविनबर्क: export PASSWORD=fooइसके बजाय और चर docker runको एक पर्यावरण चर के रूप में पारित किया जाएगा , जिससे docker run -e PASSWORDकाम बन जाएगा।
qerub

93

आप यहां बताए अनुसार @ पैराटाटा के अनुसार कमांड के -eसाथ पैरामीटर्स का इस्तेमाल कर सकते हैं । हालांकि, इस दृष्टिकोण का संभावित नकारात्मक पक्ष यह है कि आपके क्रेडेंशियल्स को प्रक्रिया सूची में प्रदर्शित किया जाएगा, जहां आप इसे चलाते हैं। यह अधिक सुरक्षित बनाने के लिए, आप एक विन्यास फाइल में आपके क्रेडेंशियल्स लिख सकते हैं और ऐसा कर सकते हैं के साथ के रूप में उल्लेख यहाँ । फिर आप उस कॉन्फिग फाइल की पहुंच को नियंत्रित कर सकते हैं ताकि दूसरों को उस मशीन तक पहुंचने में आपकी साख न दिखे।docker run ..

docker run--env-file


2
मैंने @ इरेटा के जवाब में इस चिंता को दूर करने के लिए एक और तरीका जोड़ा।
ब्रायन

21
सावधान रहें --env-file, जब आप --envअपने env मानों का उपयोग करते हैं , तो आप जो भी शेल उपयोग कर रहे हैं, उसके मानक शब्दार्थों के साथ उद्धृत / बच जाएंगे, लेकिन जब --env-fileआप अपने कंटेनर के अंदर प्राप्त मानों का उपयोग करेंगे तो अलग होगा। डॉक रन कमांड सिर्फ फ़ाइल को पढ़ता है, बहुत ही बुनियादी पार्सिंग करता है और कंटेनर के माध्यम से मूल्यों को पारित करता है, यह आपके शेल के व्यवहार के तरीके के बराबर नहीं है। अगर आप --envप्रविष्टियों का एक गुच्छा एक करने के लिए परिवर्तित कर रहे हैं बस के बारे में पता करने के लिए एक छोटा सा गोचा --env-file
छीना हुआ

5
Shorn जवाब पर विस्तार से बताने के लिए, जब env-file का उपयोग किया जाता है, तो मुझे एक लाइन पर बहुत लंबा पर्यावरण चर का मान रखना पड़ता है क्योंकि इसमें कोई लाइन ब्रेक लगाने का कोई तरीका नहीं दिखता है, या इसे विभाजित नहीं करता है कई लाइनें जैसे: $ MY_VAR = सामान $ MY_VAR = $ MY_VAR अधिक सामान
जेसन व्हाइट

53

यदि आप अपने कंटेनर (एस) को स्पिन करने की विधि के रूप में 'डॉकटर-कंपोज' का उपयोग कर रहे हैं, तो डॉकटर कंटेनर में आपके सर्वर पर परिभाषित पर्यावरण चर को पास करने का एक उपयोगी तरीका है।

अपनी docker-compose.ymlफ़ाइल में, मान लें कि आप एक बुनियादी हपी-जेएस कंटेनर को स्पिन कर रहे हैं और कोड इस तरह दिखता है:

hapi_server:
  container_name: hapi_server
  image: node_image
  expose:
    - "3000"

मान लीजिए कि आपका डॉकटर प्रोजेक्ट जिस स्थानीय सर्वर पर है, उसमें 'NODE_DB_CONNECT' नाम का एक पर्यावरण चर है जिसे आप अपने hapi-js कंटेनर में पास करना चाहते हैं, और आप इसका नया नाम 'HAPI -DB_CONNECT' चाहते हैं। फिर docker-compose.ymlफ़ाइल में, आप स्थानीय पर्यावरण चर को कंटेनर में डालेंगे और उसका नाम बदलेंगे:

hapi_server:
  container_name: hapi_server
  image: node_image
  environment:
    - HAPI_DB_CONNECT=${NODE_DB_CONNECT}
  expose:
    - "3000"

मुझे आशा है कि यह आपके कंटेनर में किसी भी फ़ाइल में डेटाबेस कनेक्ट स्ट्रिंग को हार्ड-कोडिंग से बचने में आपकी मदद करता है!


6
यह काम नहीं करेगा। उन चर को कंटेनर में पारित नहीं किया जाता है।
फ्रांउडर

@ सच में? इन डॉक्स के अनुसार ऐसा लगता है जैसे इसे होना चाहिए।
darda

1
इस दृष्टिकोण के साथ समस्या यह है कि आप doit-compose.yml फ़ाइल में पर्यावरण वेरिएबल को git रिपॉजिटरी में करते हैं जो आपको नहीं करना चाहिए। आप इसके आसपास कैसे जाते हैं? आदर्श रूप से आपके पास एक अलग env फ़ाइल होगी जो कि gitignored है और डॉकफ़राइल या docker-compose.yml में आयात / लोड कर सकती है
खालिद उस्मान

35

उपयोग करते हुए docker-compose, आप docker-compose.yml में env चर विरासत में पा सकते हैं और बाद में docker-composeछवियों का निर्माण करने के लिए किसी भी Dockerfile (s) को बुलाया जा सकता है । यह तब उपयोगी होता है जब Dockerfile RUNकमांड को पर्यावरण के लिए विशिष्ट कमांड निष्पादित करनी चाहिए।

(आपका खोल है RAILS_ENV=development पर्यावरण में पहले से मौजूद है)

docker-compose.yml :

version: '3.1'
services:
  my-service: 
    build:
      #$RAILS_ENV is referencing the shell environment RAILS_ENV variable
      #and passing it to the Dockerfile ARG RAILS_ENV
      #the syntax below ensures that the RAILS_ENV arg will default to 
      #production if empty.
      #note that is dockerfile: is not specified it assumes file name: Dockerfile
      context: .
      args:
        - RAILS_ENV=${RAILS_ENV:-production}
    environment: 
      - RAILS_ENV=${RAILS_ENV:-production}

Dockerfile :

FROM ruby:2.3.4

#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production

#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV

#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi

इस तरह से मैं न फाइल या में वातावरण चर निर्दिष्ट करने के लिए की जरूरत है docker-compose build/ upकमांड:

docker-compose build
docker-compose up

क्या उन्हें एक ही नाम होना चाहिए? लगता है कि भ्रम की स्थिति है .. और अगर मैं इसके बजाय विकास चलाना चाहता हूं तो मैं कैसे आर्गन को ओवरराइड करूंगा?
साइबरमेव

@CyberMew हाँ, उन्हें आपके पर्यावरण, डॉकटर-कम्पोज़ और डॉकरीफ़ाइल के बीच एक ही नाम होना चाहिए। यदि आप डॉकटर-कंपोज़ बिल्ड चलाने से पहले डेवलपमेंट चलाना चाहते हैं, तो पर्यावरण चर को सेट करने के लिए अपने टर्मिनल में R Colors_ENV = डेवलपमेंट चलाएं, इस तरह डॉकटर-कंपोज़ करें और बदले में Dockerfile आपके वातावरण से उस मूल्य को प्राप्त करेगा।
जोशवीर

30

उपयोग -eपर्यावरण चर (डिफ़ॉल्ट []] सेट करने के लिए या --env मान का ।

स्टार्टअप स्क्रिप्ट से एक उदाहरण:

 docker run  -e myhost='localhost' -it busybox sh

यदि आप कमांड लाइन से कई वातावरणों का उपयोग करना चाहते हैं तो प्रत्येक पर्यावरण चर का उपयोग करने से पहले -e ध्वज का ।

उदाहरण:

 sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh

नोट: सुनिश्चित करें कि कंटेनर का नाम पर्यावरण चर के बाद रखा जाए, उससे पहले नहीं।

यदि आपको कई चर सेट करने की आवश्यकता है, तो उपयोग करें --env-file ध्वज का

उदाहरण के लिए,

 $ docker run --env-file ./my_env ubuntu bash

किसी अन्य सहायता के लिए, डॉकर सहायता देखें:

 $ docker run --help

आधिकारिक दस्तावेज: https://docs.docker.com/compose/environment-variables/


2
हमें आवश्यकता क्यों है ubuntu bash? क्या यह आधार छवि या हर छवि के रूप में ubuntu के साथ बनाई गई छवियों के लिए लागू होता है?
रेयांश खरगा

काश, मैं -eतर्कों के युग के बाद कंटेनर नाम रखने के बारे में थोड़ा पढ़ता ! मुझे यह भी समझ में नहीं आ रहा है कि उन्होंने यह आवश्यक क्यों बनाया ...
लोहे की छँटाई

13

एक डॉक कंटेनर में होस्ट मशीन पर्यावरण चर को पाइप करने के लिए एक अच्छा हैक है:

env > env_file && docker run --env-file env_file image_name

इस तकनीक का उपयोग बहुत सावधानी से करें, क्योंकि सभी होस्ट मशीन ENV चर को env > env_fileडंप करेंगे और उन्हें रनिंग कंटेनर में पहुंच योग्य बनाएंगे।env_file


5

अमेज़ॅन एडब्ल्यूएस ईसीएस / ईसीआर के लिए, आपको निजी एस 3 बाल्टी के माध्यम से अपने पर्यावरण चर ( विशेष रूप से रहस्य ) का प्रबंधन करना चाहिए । Amazon S3 और Docker का उपयोग करके अमेज़ॅन EC2 कंटेनर सेवा-आधारित अनुप्रयोगों के लिए गोपनीयता का प्रबंधन कैसे करें के बारे में ब्लॉग पोस्ट देखें ।


या SSM पैरामीटर स्टोर
joshweir

5

एक अन्य तरीका शक्तियों का उपयोग करना है /usr/bin/env:

docker run ubuntu env DEBUG=1 path/to/script.sh

2

यदि आपके पास env.shस्थानीय रूप से पर्यावरण चर हैं और कंटेनर शुरू होने पर इसे स्थापित करना चाहते हैं, तो आप कोशिश कर सकते हैं

COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]

यह कमांड कंटेनर को एक बैश शेल के साथ शुरू करेगा (मुझे एक बैश शेल चाहिए क्योंकि sourceएक बैश कमांड है), env.shफाइल को स्रोत करता है (जो पर्यावरण चर को सेट करता है) और जार फाइल को निष्पादित करता है।

इस env.shतरह दिखता है,

#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"

मैंने printenvकेवल वास्तविक स्रोत कमांड काम करने के लिए कमांड को जोड़ा । स्रोत कमांड के ठीक काम करने की पुष्टि करने पर आपको इसे हटा देना चाहिए या पर्यावरण चर आपके डॉक लॉग में दिखाई देगा।


2
इस दृष्टिकोण के साथ आपको हर बार जब आप अलग / संशोधित एनवी सेट पास करना चाहते हैं, तो आपको डॉकटर छवि को फिर से बनाना होगा। "Docker --run --env-file ./somefile.txt" के दौरान envs पास करना बेहतर / गतिशील दृष्टिकोण है।
दिमित्री शेव्कोप्लस

2
@DmitryShevkoplyas मैं सहमत हूँ। मेरा उपयोग मामला वह है जहां कमांड के लिए --env-filearg को निर्दिष्ट करने का कोई विकल्प नहीं है docker run। उदाहरण के लिए, यदि आप Google एप्लिकेशन इंजन का उपयोग करके एक एप्लिकेशन को तैनात कर रहे हैं और कंटेनर के अंदर चल रहे ऐप को डॉकटर कंटेनर के अंदर पर्यावरण चर की जरूरत है, तो आपके पास पर्यावरण चर सेट करने के लिए एक सीधा दृष्टिकोण नहीं है क्योंकि आपके पास docker runकमांड पर नियंत्रण नहीं है। । ऐसी स्थिति में, आपके पास एक स्क्रिप्ट हो सकती है, जो कहती है, KMS का उपयोग करके env वेरिएबल्स को डिक्रिप्ट करता है, और उन्हें जोड़ता है, env.shजिसे env वेरिएबल्स को सेट करने के लिए सॉरी किया जा सकता है।
एकलेश राज

आप इसके बजाय .नियमित रूप से उपलब्ध POSIX (डॉट) कमांड का उपयोग कर सकते हैं । ( जैसा है )shsourcesource.
go2null

1

JSON के एनवी को बदलने के लिए jq का उपयोग करना:

env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>

इसके लिए jq संस्करण 1.6 या नए की आवश्यकता है

इस मेजबान को ईर्ष्या के रूप में जोर से मारना, अनिवार्य रूप से डॉकरफाइल में ऐसा है:

ENV HOST_ENV  (all env from the host as json)

वह रेखा आपके लिए कैसे काम कर रही है docker run -e HOST_ENV="$env_as_json" <image>?: मेरे मामले में डॉकर्स वैरिएबल के रूप में पारित होने पर चर या उपधारा ( ${}या $()) को हल करता प्रतीत नहीं होता है । उदाहरण के लिए: A=123 docker run --rm -it -e HE="$A" ubuntuफिर उस कंटेनर के अंदर: root@947c89c79397:/# echo $HE root@947c89c79397:/# .... HEचर इसे नहीं बनाता है।
पेर्फ्लेक्सबॉट

0

हम भी -E झंडा और $ का उपयोग करके मशीन पर्यावरण चर की मेजबानी कर सकते हैं:

निर्यात करने की आवश्यकता से पहले (मतलब सेट) स्थानीय एनवी चर और फ़ाइल या उपयोग करने से पहले

docker run -it -e MG_HOST=$MG_HOST -e MG_USER=$MG_USER -e MG_PASS=$MG_PASS -e MG_AUTH=$MG_AUTH -e MG_DB=$MG_DB -t image_tag_name_and_version 

मेरे मामले में आपके दिए गए नाम (MG_HOST, MG_USER) के साथ स्वचालित रूप से इस चर सेट का प्रयोग करके

अतिरिक्त:

यदि आप अजगर का उपयोग कर रहे हैं तो आप इन एनकरमेंट वैरिएबल को डॉकटर के द्वारा एक्सेस कर सकते हैं

import os
host,username,password,auth,database=os.environ.get('MG_HOST'),os.environ.get('MG_USER'),os.environ.get('MG_PASS'),os.environ.get('MG_AUTH'),os.environ.get('MG_DB')

0

docker run --rm -it --env-file <(bash -c 'env | grep <your env data>') एक तरीका है जो डेटा को एक में संग्रहीत करता है .envऔर उन्हें डॉकर के पास भेज देता है, बिना कुछ भी असुरक्षित तरीके से संग्रहीत किया जाता है (इसलिए आप केवल docker historyकुंजियों को नहीं देख सकते हैं और न ही पकड़ सकते हैं।

कहो कि आपके पास अपनी .envतरह AWS सामान का भार है :

AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx

`do do run-rm -it --env-file <(bash -c 'env | grep AWS_') के साथ रनिंग डॉक इसे सभी को पकड़कर कंटेनर के भीतर से एक्सेस करने के लिए सुरक्षित रूप से पास करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.