डॉकर में मेजबान निर्देशिका तक पहुंचने की अनुमति से इनकार किया


282

संक्षेप में: मैं डॉकर में एक मेजबान निर्देशिका को माउंट करने की कोशिश कर रहा हूं, लेकिन फिर मैं इसे कंटेनर के भीतर से एक्सेस नहीं कर सकता, भले ही एक्सेस की अनुमति अच्छी लगे।

विवरण:

मैं कर रहा हूँ

sudo docker run -i -v /data1/Downloads:/Downloads ubuntu bash

और फिर

ls -al

यह मुझे देता है:

total 8892
drwxr-xr-x.  23 root root    4096 Jun 18 14:34 .
drwxr-xr-x.  23 root root    4096 Jun 18 14:34 ..
-rwxr-xr-x.   1 root root       0 Jun 18 14:34 .dockerenv
-rwx------.   1 root root 9014486 Jun 17 22:09 .dockerinit
drwxrwxr-x.  18 1000 1000   12288 Jun 16 11:40 Downloads
drwxr-xr-x.   2 root root    4096 Jan 29 18:10 bin
drwxr-xr-x.   2 root root    4096 Apr 19  2012 boot
drwxr-xr-x.   4 root root     340 Jun 18 14:34 dev
drwxr-xr-x.  56 root root    4096 Jun 18 14:34 etc
drwxr-xr-x.   2 root root    4096 Apr 19  2012 home

और इस तरह बहुत अधिक लाइनें (मुझे लगता है कि यह प्रासंगिक हिस्सा है)।

यदि मैं करता हूँ

cd /Downloads
ls

परिणाम है

ls: cannot open directory .: Permission denied

मेजबान फेडोरा 20 है, जिसमें डॉकटर 1.0.0 और go1.2.2 है।

क्या गलत हो रहा है?

जवाबों:


269

पूरी कहानी के लिए वॉल्यूम और SELinux के बारे में इस प्रोजेक्ट एटॉमिक ब्लॉग पोस्ट को देखें ।

विशेष रूप से:

हाल ही में यह आसान हो गया क्योंकि डॉकटर ने आखिरकार एक पैच को मर्ज कर दिया जो कि docker-1.7 में दिखाई दे रहा है (हम RHEL, CentOS और Fedora पर docker-1.6 में पैच को ले जा रहे हैं)।

यह पैच वॉल्यूम mounts (-v) पर विकल्प के रूप में "z" और "Z" के लिए समर्थन जोड़ता है।

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

docker run -v /var/db:/var/db:z rhel7 /bin/sh

स्वचालित रूप chcon -Rt svirt_sandbox_file_t /var/db से मैन पेज में वर्णित किया जाएगा।

और भी बेहतर, आप Z का उपयोग कर सकते हैं।

docker run -v /var/db:/var/db:Z rhel7 /bin/sh

यह कंटेनर के अंदर की सामग्री को सटीक MCS लेबल के साथ लेबल करेगा जो कंटेनर के साथ चलेगा, मूल रूप से यह चलता है chcon -Rt svirt_sandbox_file_t -l s0:c1,c2 /var/dbजहां s0:c1,c2प्रत्येक कंटेनर के लिए अलग-अलग होता है।


18
यह एक आकर्षण की तरह काम करता है। अन्य समाधान ज्यादातर वर्कअराउंड हैं।
tuxdna

4
सीएफ वॉल्यूम डॉक्यूमेंट सेक्शन डॉक्यूमेंट डॉक्यूमेंटेशन में
maxschlepzig

ओह, यार, यह वास्तव में काम करता है। मैंने आखिरकार यह पाया। बहुत धन्यवाद! क्या इस बारे में कोई आधिकारिक दस्तावेज है?
किर्बी

1
अपस्ट्रीम में इस अनुभाग में अंतिम पैराग्राफ के रूप में है docs.docker.com/engine/reference/commandline/run/…
gregswift

1
अल्पविराम द्वारा अलग किए गए एक ही समय में दोनों विकल्पों का उपयोग करके एक ही समय में मात्रा के रूप में आसानी से बढ़ते हुए SELinux के तहत अनुमतियों को ठीक करना संभव है -v $(pwd):/app:ro,Z:। इसे सही उत्तर के रूप में चिह्नित किया जाना चाहिए।
डेनियारोड

263

यह एक SELinux समस्या है।

आप अस्थायी रूप से जारी कर सकते हैं

su -c "setenforce 0"

होस्ट पर एक्सेस करने के लिए या फिर रन करके एक SELinux नियम जोड़ें

chcon -Rt svirt_sandbox_file_t /path/to/volume

3
होस्ट के पथ को / पथ / से / मात्रा है? यदि ऐसा है तो ऐसा नहीं लगता कि यह समाधान डेटा कंटेनरों के साथ काम करेगा?
रॉय Truelove

6
su -c "setenforce 1" करना न भूलें ... अन्यथा यह केवल इसलिए काम करेगा क्योंकि SELinux अभी भी निष्क्रिय है
vcarel

इससे मेरी समस्या हल हो गई। धन्यवाद, मुझे आशा है कि वे इसके लिए एक तय करेंगे।
होकुत्सोइ

19
सेलिनक्स नियम को जोड़ना सबसे अच्छा तरीका है, क्योंकि ज्यादातर मामलों में विशेषाधिकार प्राप्त मोड के साथ कंटेनर चलाना एक अच्छा विचार नहीं है।
Zoro_77

7
जैसा कि Zoro_77 ने कहा, एक नियम और stopdisablingselinux.com ;) जोड़ें
GabLeRoux

71

चेतावनी: इस समाधान में सुरक्षा जोखिम हैं।

कंटेनर को विशेषाधिकार के रूप में चलाने का प्रयास करें:

sudo docker run --privileged=true -i -v /data1/Downloads:/Downloads ubuntu bash

एक अन्य विकल्प (कि मैंने कोशिश नहीं की है) एक विशेषाधिकार प्राप्त कंटेनर बनाना और फिर उसके अंदर गैर-विशेषाधिकार प्राप्त कंटेनर बनाना होगा।


1
@JBernardo समस्या का हल किन दो विकल्पों में से है?
15:100 बजे user100464

@ user100464--privileged=true
JBernardo

1
मेरे मामले में मदद मत करो। डेबियन व्हीज़्ज़ी बैकपोर्टेड कर्नेल 3.16 के साथ लेकिन सिलेक्टिन कॉन्फ़िगरेशन सक्रिय नहीं। :(
एहोल्ब्रिच

यदि आपका प्रयोग करने वाला संगीतकार 'विशेषाधिकार प्राप्त: सच्चा' जोड़ता है
लियोनेल मॉरिसन

35
यह मत करो। --privilegedएक सुरक्षा जोखिम है
नवीन

38

सामान्यतया, होस्ट वॉल्यूम माउंट के साथ अनुमतियाँ समस्याएँ होती हैं क्योंकि कंटेनर के अंदर uid / gid के पास फ़ाइल की पहुँच होस्ट के अनुसार फ़ाइल की uid / gid अनुमतियों के अनुसार नहीं होती है। हालाँकि, यह विशिष्ट मामला अलग है।

अनुमति स्ट्रिंग के अंत में स्थित drwxr-xr-x., इंगित करता है कि SELinux कॉन्फ़िगर किया गया है। SELinux के साथ होस्ट माउंट का उपयोग करते समय, आपको वॉल्यूम परिभाषा के अंत में एक अतिरिक्त विकल्प पास करना होगा:

  • zविकल्प इंगित करता है कि सामग्री के लिए बाध्य माउंट कई कंटेनर के बीच साझा किया जाता है।
  • Zविकल्प इंगित करता है कि सामग्री के लिए बाध्य माउंट निजी और साझा नहीं की है।

आपका वॉल्यूम माउंट कमांड तब दिखेगा:

sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash

SELinux के होस्ट होस्टों के बारे में अधिक जानकारी के लिए देखें: https://docs.docker.com/storage/#configure-the-selinux-label


दूसरों के लिए जो इस मुद्दे को एक अलग उपयोगकर्ता के रूप में चल रहे कंटेनरों के साथ देखते हैं, आपको यह सुनिश्चित करने की आवश्यकता है कि कंटेनर के अंदर उपयोगकर्ता के यूआईडी / gid को होस्ट पर फ़ाइल की अनुमति है। उत्पादन सर्वरों पर, यह अक्सर छवि निर्माण प्रक्रिया में यूआईडी / जीआईडी ​​को नियंत्रित करके होस्ट पर एक यूआईडी / जीआईडी ​​से मिलान करने के लिए किया जाता है, जिसकी फाइलों तक पहुंच होती है (या इससे भी बेहतर, उत्पादन में होस्ट माउंट का उपयोग नहीं करते हैं)।

एक नामित वॉल्यूम को अक्सर आरोहित होस्ट करने के लिए पसंद किया जाता है क्योंकि यह छवि निर्देशिका से वॉल्यूम निर्देशिका को आरंभ करेगा, जिसमें कोई फ़ाइल स्वामित्व और अनुमतियाँ शामिल हैं। यह तब होता है जब वॉल्यूम खाली होता है और कंटेनर को नामित वॉल्यूम के साथ बनाया जाता है।

MacOS उपयोगकर्ताओं के पास अब OSXFS है जो मैक होस्ट और कंटेनरों के बीच स्वचालित रूप से uid / gid को हैंडल करता है। एक जगह जिसके साथ यह मदद नहीं करता है वह एम्बेडेड वीएम के अंदर की फाइलें हैं जो कंटेनर में घुड़सवार होती हैं, जैसे /var/lib/docker.sock।

विकास के वातावरण के लिए, जहाँ होस्ट यूआईडी / जीआईडी ​​प्रति डेवलपर बदल सकता है, मेरा पसंदीदा समाधान कंटेनर को रूट के रूप में चलाने वाले एंट्रीपॉइंट के साथ शुरू करना है, होस्ट वॉल्यूम यूआईडी / जीआईडी ​​से मिलान करने के लिए कंटेनर के अंदर उपयोगकर्ता के यूआईडी / जीआईडी ​​को ठीक करना, और फिर gosuकंटेनर के अंदर एप्लिकेशन को चलाने के लिए कंटेनर उपयोगकर्ता को रूट से ड्रॉप करने के लिए उपयोग करें। इसके लिए महत्वपूर्ण स्क्रिप्ट fix-permsमेरी आधार छवि लिपियों में है, जो यहां देखी जा सकती है: https://github.com/sudo-bmitch/docker-base

fix-permsस्क्रिप्ट से महत्वपूर्ण बिट है:

# update the uid
if [ -n "$opt_u" ]; then
  OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
  NEW_UID=$(stat -c "%u" "$1")
  if [ "$OLD_UID" != "$NEW_UID" ]; then
    echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
    usermod -u "$NEW_UID" -o "$opt_u"
    if [ -n "$opt_r" ]; then
      find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
    fi
  fi
fi

कंटेनर के अंदर उपयोगकर्ता की फ़ाइल, और फ़ाइल के यूआईडी से यूआईडी प्राप्त होता है, और यदि वे मेल नहीं खाते हैं, usermodतो यूआईडी को समायोजित करने के लिए कॉल करता है। अंत में यह उन फ़ाइलों को ठीक करने के लिए एक पुनरावर्ती खोज करता है जो यूआईडी नहीं बदले हैं। मुझे -u $(id -u):$(id -g)ध्वज के साथ कंटेनर चलाने से बेहतर यह पसंद है क्योंकि उपरोक्त प्रविष्टि बिंदु कोड को कंटेनर को शुरू करने के लिए प्रत्येक डेवलपर को स्क्रिप्ट चलाने की आवश्यकता नहीं है, और उपयोगकर्ता के स्वामित्व वाले वॉल्यूम के बाहर की किसी भी फाइल को उनकी अनुमति सही होगी।


आप एक डैम को बांधने वाले नाम वाले वॉल्यूम का उपयोग करके किसी छवि से एक होस्ट निर्देशिका को प्रारंभ कर सकते हैं। यह निर्देशिका पहले से मौजूद होनी चाहिए, और आपको किसी कंपोज़ फ़ाइल में होस्ट वॉल्यूम के विपरीत होस्ट निर्देशिका के लिए एक पूर्ण पथ प्रदान करना होगा, जो सापेक्ष पथ हो सकते हैं। इसे आरंभ करने के लिए निर्देशिका को docker के लिए खाली होना चाहिए। बाइंड माउंट देखने के लिए नामांकित वॉल्यूम को परिभाषित करने के लिए तीन अलग-अलग विकल्प जैसे:

  # create the volume in advance
  $ docker volume create --driver local \
      --opt type=none \
      --opt device=/home/user/test \
      --opt o=bind \
      test_vol

  # create on the fly with --mount
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
    foo

  # inside a docker-compose file
  ...
  volumes:
    bind-test:
      driver: local
      driver_opts:
        type: none
        o: bind
        device: /home/user/test
  ...

अंत में, यदि आप उपयोगकर्ता नामस्थानों का उपयोग करने का प्रयास करते हैं, तो आप पाएंगे कि होस्ट संस्करणों के पास अनुमति के मुद्दे हैं क्योंकि कंटेनरों के uid / gid को स्थानांतरित कर दिया गया है। इस परिदृश्य में, मेजबान संस्करणों से बचना संभव है और केवल नामांकित संस्करणों का उपयोग करें।


32

से access.redhat.com:Sharing_Data_Across_Containers :

होस्ट वॉल्यूम सेटिंग्स पोर्टेबल नहीं हैं, क्योंकि वे होस्ट-निर्भर हैं और किसी अन्य मशीन पर काम नहीं कर सकते हैं। इस कारण से, कंटेनर में बढ़ते होस्ट निर्देशिकाओं के लिए कोई डॉकरफ़ाइल समकक्ष नहीं है। इसके अलावा, ध्यान रखें कि मेजबान सिस्टम को कंटेनर SELinux नीति का कोई ज्ञान नहीं है। इसलिए, यदि SELinux नीति लागू की जाती है, तो आरडब्ल्यू सेटिंग की परवाह किए बिना, घुड़सवार होस्ट निर्देशिका कंटेनर के लिए उपयुक्त नहीं है। वर्तमान में, आप इसके लिए होस्ट निर्देशिका में उचित SELinux नीति प्रकार निर्दिष्ट करके काम कर सकते हैं ":

chcon -Rt svirt_sandbox_file_t host_dir

जहाँ host_dir कंटेनर पर आरूढ़ होने वाली होस्ट सिस्टम पर निर्देशिका का पथ है।

यह केवल एक वर्कअराउंड प्रतीत होता है, लेकिन मैंने कोशिश की और यह काम करता है।


14

मैंने सत्यापित किया कि chcon -Rt svirt_sandbox_file_t /path/to/volumeकाम करता है और आपको विशेषाधिकार प्राप्त कंटेनर के रूप में नहीं चलना है।

यह चालू है:

  • डॉकर संस्करण 0.11.1-देव, 02d20af / 0.11.1 का निर्माण करें
  • होस्ट और कंटेनर के रूप में SELOS के साथ CentOS 7 सक्षम है।

2
डॉकर के भीतर रीलेबल करने के लिए आधिकारिक समर्थन के लिए github.com/docker/docker/pull/5910 देखें ।
cpuguy83 14

13

कोशिश करो docker volume create

mkdir -p /data1/Downloads
docker volume create --driver local --name hello --opt type=none --opt device=/data1/Downloads --opt o=uid=root,gid=root --opt o=bind
docker run -i -v hello:/Downloads ubuntu bash

दस्तावेज़ https://docs.docker.com/engine/reference/commandline/volume_create/ पर एक नज़र डालें


3
एसओ पर इस मुद्दे के बारे में बहुत सारे जवाब देने की कोशिश की, लेकिन वास्तव में इसने मदद की। धन्यवाद!
पॉल

इसने अनुमति की त्रुटि को हल कर दिया है ।लेकिन अब अगर मैं भौतिक स्थान को माउंट करने की कोशिश कर रहा हूं तो यह उलटी पड़ती है ???? @ कपेन
कुणाल वर्मा

1
@kunalverma हां। यदि आपको यह पसंद नहीं है, तो यहां आसान जवाब है। stackoverflow.com/a/31334443/4909388
9

4

मेरे पास एक समान मुद्दा था, मेरा मेजबान के यूआईडी और कंटेनर के उपयोगकर्ता के यूआईडी के बीच एक बेमेल के कारण हुआ था। फ़िक्स को उपयोगकर्ता के यूआईडी को पास करने और एक ही यूआईडी के साथ कंटेनर के उपयोगकर्ता को बनाने के लिए एक तर्क के रूप में पारित करना था।

DockerFile में:

ARG UID=1000
ENV USER="ubuntu"
RUN useradd -u $UID -ms /bin/bash $USER

बिल्ड चरण में:

docker build <path/to/Dockerfile> -t <tag/name> --build-arg UID=$UID

उसके बाद, ओपी के अनुसार कंटेनर और कमांड चलाने से मुझे अपेक्षित परिणाम मिला।


1
क्या होगा यदि आप रन-टाइम तक यूआईडी नहीं जानते हैं? (मैं कुछ उपकरणों के पैकेज के लिए एक छवि बना रहा हूं, जो अपने फाइल सिस्टम पर वापस लिखते हैं, लेकिन उनके पास अलग-अलग यूआईडी हैं)। मुझे लगता है कि मैं इसे रूट और केवल एड्यूसर ही रख सकता हूं?
Inger

मेरे पास इसका कोई अच्छा जवाब नहीं है, दुर्भाग्य से। अगर किसी और के पास एक समाधान है तो मुझे इसमें दिलचस्पी होगी। मुझे संदेह है कि डॉकर एंट्रीपॉइंट की कार्यक्षमता एक समाधान प्रदान कर सकती है।
RoboCop87

0

मैंने डेटा कंटेनर का उपयोग करके उस समस्या को हल किया, इससे एप्लिकेशन परत से डेटा को अलग करने का भी लाभ होता है। आप इसे इस तरह से चला सकते हैं:

docker run --volumes-from=<container-data-name> ubuntu

यह ट्यूटोरियल डेटा कंटेनरों के उपयोग पर एक अच्छा विवरण प्रदान करता है।


-1

मेरी स्थिति में समस्या अलग थी। मुझे पता नहीं क्यों, लेकिन भले ही होस्ट पर निर्देशिका उस पर chmod 777चल रही थी , डॉक के अंदर यह दिखाई दे रहा था 755

कंटेनर के अंदर भागते हुए sudo chmod 777 my_volume_dirइसे ठीक कर दिया।


5
chmod 777शायद ही कभी कुछ ठीक करता है।
एरकी

मुझे क्षमा करें, लेकिन आप इस बिंदु से चूक गए हैं। मुद्दा यह है कि कंटेनर के अंदर विशेषाधिकार कम कर दिए गए थे और इसे बाहर से तय नहीं किया जा सकता था।
कोडसैंडविच

-2

sudo -s मेरे लिए चाल पर MAC


1
यदि आप नीच हैं, तो एक टिप्पणी छोड़ें और समझाएं कि क्यों। मुझे ठीक उसी मुद्दे का सामना करना पड़ा और मैं सूडो-एस द्वारा इसे हल करने में सक्षम था।
नचिकेत जोशी

प्रत्येक docker की छवि में sudo नहीं है, और यह हर परिदृश्य में संभव नहीं है।
SOFe

2
कंटेनरों पर sudo स्थापित न करें। एक हमलावर एक कंटेनर के अंदर सुडो का उपयोग कर सकता है।
अर्नोल्ड बल्लियू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.