Docker और --userns-remap, होस्ट और कंटेनर के बीच डेटा साझा करने के लिए वॉल्यूम अनुमतियों का प्रबंधन कैसे करें?


96

डॉकटर में, कंटेनरों के अंदर बनाई गई फाइलें होस्ट से निरीक्षण करते समय अप्रत्याशित स्वामित्व रखती हैं। वॉल्यूम पर फ़ाइलों का स्वामी डिफ़ॉल्ट रूप से रूट (uid 0) है, लेकिन जैसे ही गैर-रूट उपयोगकर्ता खाते कंटेनर में शामिल होते हैं और फ़ाइल सिस्टम पर लिखते हैं, मालिक होस्ट के परिप्रेक्ष्य से कम या ज्यादा यादृच्छिक हो जाते हैं।

यह एक समस्या है जब आपको होस्ट से वॉल्यूम डेटा को उसी उपयोगकर्ता खाते का उपयोग करने की आवश्यकता होती है जो डॉक कमांड को कॉल कर रहा है।

विशिष्ट कार्यपत्रक होते हैं

  • Dockerfiles (गैर पोर्टेबल) में निर्माण समय पर उपयोगकर्ताओं को मजबूर करना
  • होस्ट उपयोगकर्ता के UID को docker runकमांड को एक पर्यावरण चर के रूप में पास करना और फिर chownएक एंट्रीपॉइंट स्क्रिप्ट में वॉल्यूम पर कुछ कमांड चलाना ।

ये दोनों समाधान कंटेनर के बाहर वास्तविक अनुमतियों पर कुछ नियंत्रण दे सकते हैं।

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

मान लीजिए मैं इस बुनियादी कंटेनर को शुरू करता हूं

docker run -ti -v /data debian:jessie /bin/bash
echo 'hello' > /data/test.txt
exit

और फिर मेजबान से सामग्री का निरीक्षण करें:

ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/

-rw-r--r-- 1 100000 100000 6 Feb  8 19:43 test.txt

यह संख्या '100000' मेरे होस्ट उपयोगकर्ता का एक उप-यूआईडी है, लेकिन चूंकि यह मेरे उपयोगकर्ता के यूआईडी के अनुरूप नहीं है, इसलिए मैं अभी भी विशेषाधिकारों के बिना test.txt को संपादित नहीं कर सकता। इस उप-उपयोगकर्ता को मेरे वास्तविक नियमित उपयोगकर्ता के साथ डॉकटर के बाहर कोई संबंध नहीं लगता है। यह वापस मैप नहीं है।

इस पोस्ट में पहले बताए गए वर्कअराउंड शामिल हैं, जिसमें होस्ट और कंटेनर के बीच यूआईडी को संरेखित करना शामिल है UID->sub-UIDजो नामस्थान में होने वाली मैपिंग के कारण अब काम नहीं करता है।

फिर, क्या उपयोगकर्ता नेमस्पेस सक्षम (बेहतर सुरक्षा के लिए) के साथ डॉक चलाने का एक तरीका है, जबकि अभी भी वॉल्यूम पर उत्पन्न फ़ाइलों को चलाने के लिए होस्ट उपयोगकर्ता के लिए डॉक चलाने के लिए संभव है?


मुझे लगता है कि यदि आप होस्ट और कंटेनर के बीच वॉल्यूम साझा करने जा रहे हैं, तो उपयोगकर्ता नामस्थान समाधान का हिस्सा नहीं होंगे। आपका दूसरा विकल्प ("होस्ट उपयोगकर्ता के यूआईडी को डॉक करने वाले को एक पर्यावरण चर के रूप में चलाने के लिए और फिर एक एंट्रीपॉइंट स्क्रिप्ट में वॉल्यूम पर कुछ चाउन कमांड चलाने के लिए") शायद सबसे अच्छा समाधान है।
लार्क्स

4
डॉकर खुद को होस्ट-माउंटेड लेखन योग्य वॉल्यूम का उपयोग करने के लिए प्रोत्साहित नहीं करता है। चूंकि मैं क्लाउड सेवा नहीं चला रहा हूं और केवल अपने स्वयं के विश्वसनीय चित्रों का उपयोग कर रहा हूं, इसलिए अब मैं सोच रहा हूं कि क्या उपयोगकर्ता एनएस का सुरक्षा लाभ इतनी सुविधा के लायक है।
स्टीफन सी।

@ StéphaneC। क्या आपको शायद बेहतर दृष्टिकोण मिला है?
अठारह

4
दुर्भाग्य से नहीं, उपयोगकर्ता नाम स्थान का उपयोग नहीं करना और मेजबान से यूआईडी पारित करना अभी भी मेरी पसंद का विकल्प है। मुझे उम्मीद है कि भविष्य में उपयोगकर्ताओं को मैप करने का एक उचित तरीका होगा। मुझे इसमें संदेह है लेकिन फिर भी, मैं एक आंख खुली रखता हूं।
स्टीफन C.

जवाबों:


46

यदि आप उपयोगकर्ताओं और समूहों को पहले से व्यवस्थित कर सकते हैं, तो यूआईडी और जीआईडी ​​को इस तरह से निर्दिष्ट करना संभव है, ताकि मेजबान उपयोगकर्ता कंटेनरों के अंदर नामांकित उपयोगकर्ताओं के अनुरूप हों।

इसका एक उदाहरण (Ubuntu 14.04, Docker 1.10) है:

  1. निश्चित संख्यात्मक आईडी वाले कुछ उपयोगकर्ता बनाएं:

    useradd -u 5000 ns1
    
    groupadd -g 500000 ns1-root
    groupadd -g 501000 ns1-user1
    
    useradd -u 500000 -g ns1-root ns1-root
    useradd -u 501000 -g ns1-user1 ns1-user1 -m
    
  2. मैन्युअल रूप से ऑटो-जेनरेट की गई अधीनस्थ ID श्रेणियों /etc/subuidऔर /etc/subgidफ़ाइलों को संपादित करें :

    ns1:500000:65536
    

    (ध्यान दें वहाँ के लिए कोई रिकॉर्ड कर रहे हैं ns1-rootऔर ns1-user1की वजह से MAX_UIDऔर MAX_GIDमें सीमा /etc/login.defs)

  3. इसमें उपयोगकर्ता नामस्थान सक्षम करें /etc/default/docker:

    DOCKER_OPTS="--userns-remap=ns1"
    

    डेमॉन को पुनरारंभ service docker restartकरें, सुनिश्चित करें कि /var/lib/docker/500000.500000निर्देशिका बनाई गई है।

    अब, कंटेनर के अंदर rootऔर आपके पास user1, और मेजबान पर - ns1-rootऔर ns1-user1, मेल आईडी के साथ

    अद्यतन: यह सुनिश्चित करने के लिए कि गैर-रूट उपयोगकर्ताओं ने कंटेनरों में आईडी तय की है (उदाहरण के लिए उपयोगकर्ता 1000: 1000), उन्हें छवि निर्माण के लिए स्पष्ट रूप से बनाएं।

टेस्ट ड्राइव:

  1. वॉल्यूम डायरेक्टरी तैयार करें

    mkdir /vol1
    chown ns1-root:ns1-root /vol1
    
  2. कंटेनर से इसे आज़माएं

    docker run --rm -ti -v /vol1:/vol1 busybox sh
    echo "Hello from container" > /vol1/file
    exit
    
  3. मेजबान से कोशिश करें

    passwd ns1-root
    login ns1-root
    cat /vol1/file
    echo "can write" >> /vol1/file
    

पोर्टेबल नहीं है और हैक की तरह दिखता है, लेकिन काम करता है।


3
बहुत ही रोचक और एक योग्य है। लेकिन फिर भी आपको यह सुनिश्चित करने की आवश्यकता होगी कि आपकी छवि में उपयोगकर्ता 1 को यूआईडी 1000 सौंपा गया है। अन्यथा आप यह सुनिश्चित नहीं कर सकते कि यह मेजबान पर यूआईडी 501000 प्राप्त करेगा। Btw क्या हमें पूरा यकीन है कि सूत्र हमेशा होता है subUID lower bound + UID in imageअगर हम एक उपयोगकर्ता के साथ कई अलग-अलग छवियां चला रहे हैं जिनके पास आईडी है जो 1000 पर सेट है?
स्टीफन सी।

@ StéphaneC। अच्छी बात! छवियों के अंदर आईडी को ठीक करने के बारे में एक नोट जोड़ा गया। सूत्र के अनुसार, मैं अपनी खुद की छवियों के साथ आगे प्रयोग करने जा रहा हूं और यदि कुछ भी मिल जाए तो उत्तर को अपडेट कर दूंगा
amartynov

1
यदि आप होस्ट और कंटेनरों में उपयोगकर्ताओं और समूहों की व्यवस्था करते हैं, तो क्या आपको वास्तव में "यूजर नेमस्पेस" सुविधा की आवश्यकता है?
ट्रिस्टन

1
आपके द्वारा बनाए गए नामस्थान होस्ट उपयोगकर्ताओं को कंटेनर उपयोगकर्ताओं से अलग करते हैं, लेकिन आपको कंटेनरों के लिए कई नामस्थानों की आवश्यकता हो सकती है, खासकर जब आधिकारिक चित्र (जैसे mysql एक) स्पष्ट यूआईडी के बिना एक उपयोगकर्ता बनाते हैं। जब आप केवल एक ही अपेक्षा करते हैं, तो आप कई नामस्थानों के साथ कैसे व्यवहार करते हैं?
ट्रिस्टन

2
@amartynov मैं पूछ सकता हूं कि आपने अपने "ns1" उपयोगकर्ता के लिए UID (5000) को निर्दिष्ट करने के लिए परेशानी क्यों उठाई? चूँकि यह नाम (यूआईडी नहीं) है जिसे आप सब्यूड और सबगिड फाइलों में संदर्भित करते हैं, ऐसा लगता है कि यह यूआईडी को इस उपयोगकर्ता को नहीं मिलता है। क्या मुझे कुछ संबंध याद आ रहे हैं, क्योंकि 5000 और 500000 के बीच समानता सुझाव दे सकती है?
जॉलीमॉर्फिक

2

एक वर्कअराउंड गतिशील रूप से उपयोगकर्ता के यूआईडी को होस्ट से मिलान करने के लिए बिल्ड टाइम पर असाइन करना है।

उदाहरण Dockerfile:

FROM ubuntu
# Defines argument which can be passed during build time.
ARG UID=1000
# Create a user with given UID.
RUN useradd -d /home/ubuntu -ms /bin/bash -g root -G sudo -u $UID ubuntu
# Switch to ubuntu user by default.
USER ubuntu
# Check the current uid of the user.
RUN id
# ...

तब के रूप में निर्माण:

docker build --build-arg UID=$UID -t mycontainer .

और निम्नानुसार चलाएं:

docker run mycontainer

यदि आपके पास मौजूदा कंटेनर है, तो निम्न के साथ एक आवरण कंटेनर बनाएं Dockerfile:

FROM someexistingcontainer
ARG UID=1000
USER root
# This assumes you've the existing user ubuntu.
RUN usermod -u $UID ubuntu
USER ubuntu

इसे इस docker-compose.ymlतरह से लपेटा जा सकता है :

version: '3.4'
services:
  myservice:
    command: id
    image: myservice
    build:
      context: .
    volumes:
    - /data:/data:rw

फिर निर्माण और चलाने के रूप में:

docker-compose build --build-arg UID=$UID myservice; docker-compose run myservice

1
मैं अमित्र नहीं देखना चाहता, लेकिन यह वास्तव में मूल प्रश्न में सूचीबद्ध वर्कअराउंड में से एक है, लेकिन समाधान नहीं है और उपयोगकर्ता नामस्थान से संबंधित नहीं है।
स्टीफन सी।

@ StéphaneC। क्या आप इस संबंधित प्रश्न पर टिप्पणी कर सकते हैं? stackoverflow.com/questions/60274418/…
ओवरएक्सचेंज

-1

आप docker cpकमांड का उपयोग करके अनुमति की समस्याओं से बच सकते हैं ।

गंतव्य पर उपयोगकर्ता और प्राथमिक समूह के लिए स्वामित्व सेट है। उदाहरण के लिए, कंटेनर में प्रतिलिपि की गई फ़ाइलें UID:GIDरूट उपयोगकर्ता के साथ बनाई जाती हैं । स्थानीय मशीन में कॉपी की गई फाइलें UID:GIDउपयोगकर्ता के साथ बनाई जाती हैं , जो docker cpकमांड को आमंत्रित करती है ।

यहां आपके उदाहरण का उपयोग करने के लिए स्विच किया गया है docker cp:

$ docker run -ti -v /data debian:jessie /bin/bash
root@e33bb735a70f:/# echo 'hello' > /data/test.txt
root@e33bb735a70f:/# exit
exit
$ docker volume ls
DRIVER              VOLUME NAME
local               f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93
$ sudo ls -l /var/lib/docker/100000.100000/volumes/f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93/_data
total 4
-rw-r--r-- 1 100000 100000 6 Oct  6 10:34 test.txt
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
e33bb735a70f        debian:jessie       "/bin/bash"         About a minute ago   Exited (0) About a minute ago                       determined_hypatia
$ docker cp determined_hypatia:/data/test.txt .
$ ls -l test.txt 
-rw-r--r-- 1 don don 6 Oct  6 10:34 test.txt
$ cat test.txt
hello
$ 

हालाँकि, यदि आप किसी कंटेनर में से फ़ाइलें पढ़ना चाहते हैं, तो आपको नामांकित वॉल्यूम की आवश्यकता नहीं है। यह उदाहरण एक नामित मात्रा के बजाय एक नामित कंटेनर का उपयोग करता है:

$ docker run -ti --name sandbox1 debian:jessie /bin/bash
root@93d098233cf3:/# echo 'howdy' > /tmp/test.txt
root@93d098233cf3:/# exit
exit
$ docker cp sandbox1:/tmp/test.txt .
$ ls -l test.txt
-rw-r--r-- 1 don don 6 Oct  6 10:52 test.txt
$ cat test.txt
howdy
$ 

जब मुझे इस प्रश्न में वर्णित किया गया है, तो मुझे नामांकित वॉल्यूम उपयोगी लगते हैं, जब मैं फ़ाइलों को एक कंटेनर में कॉपी करना चाहता हूं ।


लेकिन docker cpडुप्लिकेट डेटा शामिल है। इसके अलावा, डॉक्टर के अनुसार, जब किसी कंटेनर में डेटा कॉपी किया जाता है, तो वह रूट उपयोगकर्ता के अनुसार स्वामित्व आईडी निर्धारित करता है, जो अक्सर कंटेनर ऐप चलाने वाला खाता नहीं होता है। मैं यह देखने में विफल हूं कि यह हमारी समस्या को कैसे हल करता है।
स्टीफन सी।

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