Docker'da ana bilgisayar dizinine erişme izni reddedildi


283

Kısacası: Docker'da bir ana bilgisayar dizini kurmaya çalışıyorum, ancak erişim izinleri iyi görünse bile, kapsayıcıdan ona erişemiyorum.

Ayrıntılar:

yapıyorum

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

ve sonra

ls -al

Bana verir:

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

ve bunun gibi daha fazla satır (bence bu ilgili bölüm).

Eğer yaparsam

cd /Downloads
ls

sonuç

ls: cannot open directory .: Permission denied

Ev sahibi, Docker 1.0.0 ve go1.2.2 ile Fedora 20'dir.

Neler yanlış gidiyor?

Yanıtlar:


269

Tüm hikaye için Volumes ve SELinux ile ilgili bu Project Atomic blog yayınına bakın .

özellikle:

Docker nihayet docker-1.7'de görünecek bir yamayı birleştirdiğinden bu son zamanlarda daha kolay oldu (yamayı RHEL, CentOS ve Fedora'da docker-1.6'da taşıyoruz).

Bu düzeltme eki, birim bağlarındaki (-v) seçenekler olarak "z" ve "Z" için destek ekler.

Örneğin:

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

chcon -Rt svirt_sandbox_file_t /var/db Man sayfasında açıklananları otomatik olarak yapar .

Daha da iyisi, Z'yi kullanabilirsiniz.

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

Bu, kabın içindeki içeriği, kabın çalışacağı tam MCS etiketiyle etiketleyecektir, temel olarak her kap için farklı chcon -Rt svirt_sandbox_file_t -l s0:c1,c2 /var/dbyerlerde çalışır s0:c1,c2.


18
Bu bir cazibe gibi çalışır. Diğer çözümler çoğunlukla geçici çözümlerdir.
tuxdna


Oh, adamım, gerçekten işe yarıyor. Sonunda buldum. Çok teşekkürler! Bununla ilgili resmi bir belge var mı?
Kirby

1
Yukarı akış, bu bölümdeki son paragraf olarak sahiptir docs.docker.com/engine/reference/commandline/run/…
gregswift

1
Bir virgülle ayırarak aynı anda her iki seçeneklerini kullanarak aynı anda salt okunur olarak hacmini montaj sırasında SELinux altında izinleri düzeltmek mümkündür: -v $(pwd):/app:ro,Z. Bu doğru cevap olarak işaretlenmelidir.
danirod

264

Bu bir SELinux sorunudur.

Geçici olarak yayınlayabilirsiniz

su -c "setenforce 0"

çalıştırabilir veya çalıştırarak SELinux kuralı ekleyebilir

chcon -Rt svirt_sandbox_file_t /path/to/volume

3
/ path / to / volume ana bilgisayarın yolu mu? Öyleyse, bu çözümün veri kapları ile çalışacağı görülmüyor mu?
Roy Truelove

6
su -c "setenforce 1" yapmayı unutmayın ... aksi takdirde sadece SELinux hala devre dışı olduğu için çalışır
vcarel

bu benim sorunumu çözdü. teşekkür ederim, umarım bunun için bir düzeltme olacaktır.
Hokutosei

19
Selinux kuralını eklemek en iyi yoldur, çünkü çoğu durumda kapsayıcıları ayrıcalıklı modda çalıştırmak iyi bir fikir değildir.
Zoro_77

7
Zoro_77'nin dediği gibi, bir kural ekleyin ve stopdisablingselinux.com ;)
GabLeRoux

71

UYARI: Bu çözümün güvenlik riskleri vardır.

Kapsayıcıyı ayrıcalıklı olarak çalıştırmayı deneyin:

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

Başka bir seçenek (denemedim) ayrıcalıklı bir kapsayıcı oluşturmak ve daha sonra içinde ayrıcalıklı olmayan kapsayıcılar oluşturmak olacaktır.


1
@JBernardo İki seçenekten hangisi sorunu çözdü?
user100464

@ user100464--privileged=true
JBernardo

1
Benim durumumda yardım etmeyin. Debian Whezzy, backported çekirdek 3.16 ile fakat aktif SELinux konfigürasyonu ile. :(
aholbreich

Eğer docker-composer 'ayrıcalıklı: true' eklerseniz
Lionel Morrison

35
Bunu yapma. --privilegedbir güvenlik riskidir
Navin

38

Genellikle, ana bilgisayar birimi bağlama birimiyle ilgili izin sorunları, kapsayıcı içindeki uid / gid, ana bilgisayardaki dosyanın uid / gid izinlerine göre dosyaya erişememesidir. Ancak, bu özel durum farklıdır.

İzin dizesinin sonundaki nokta, drwxr-xr-x.SELinux'un yapılandırıldığını gösterir. SELinux ile bir ana bilgisayar bağlantısı kullanırken, birim tanımının sonuna fazladan bir seçenek iletmeniz gerekir:

  • zSeçenek monte Bind içeriğin birden fazla kaplarda arasında paylaşılan olduğunu gösterir.
  • ZSeçenek monte Bind içeriği gizli ve paylaşılmamış olduğunu gösterir.

Birim bağlama komutunuz şöyle görünecektir:

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

SELinux ile ana bilgisayar bağlantıları hakkında daha fazla bilgi için: https://docs.docker.com/storage/#configure-the-selinux-label


Farklı bir kullanıcı olarak çalışan kapsayıcılar ile bu sorunu gören diğerleri için, kapsayıcı içindeki kullanıcının uid / gid'in ana bilgisayardaki dosyaya izinleri olduğundan emin olmanız gerekir. Üretim sunucularında, bu genellikle görüntü oluşturma işlemindeki uid / gid'i, dosyalara erişimi olan ana bilgisayardaki bir uid / gid ile eşleşecek şekilde denetleyerek yapılır (veya daha da iyisi, üretimde ana bilgisayar bağlarını kullanmayın).

Adlandırılmış bir birim, ana bilgisayar bağları için genellikle tercih edilir, çünkü herhangi bir dosya sahipliği ve izinleri de dahil olmak üzere birim dizinini görüntü dizininden başlatır. Bu, birim boş olduğunda ve kap belirtilen birimle oluşturulduğunda gerçekleşir.

MacOS kullanıcıları artık Mac ana bilgisayarı ve kapsayıcılar arasında uid / gid'leri otomatik olarak işleyen OSXFS'ye sahip. Yardım etmediği bir yer, /var/lib/docker.sock gibi, kabın içine monte edilen gömülü VM'nin içindeki dosyalardır.

Ana bilgisayar uid / gid'in geliştirici başına değişebileceği geliştirme ortamları için, tercih ettiğim çözüm, kapsayıcıyı kök olarak çalışan bir giriş noktasıyla başlatmak, kullanıcının uid / gid'i ana bilgisayar hacmine uid / gid ile eşleşecek şekilde kap içinde düzeltmek ve daha sonra gosuuygulamayı kap içinde çalıştırmak için kökten kapsayıcı kullanıcısına bırakmak için kullanın. Bunun için önemli komut dosyası fix-permsşu adreste bulunan temel resim komut dosyalarındadır: https://github.com/sudo-bmitch/docker-base

fix-permsSenaryonun önemli kısmı:

# 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

Bu, kullanıcının kapsayıcısının uid değerini ve dosyanın uid'ini alır ve eşleşmezlerse, usermoduid'i ayarlamak için çağrı yapar. Son olarak uid en değişmemiş dosyaları düzeltmek için özyinelemeli bir bulma yapar. -u $(id -u):$(id -g)Yukarıdaki giriş noktası kodu kapsayıcıyı başlatmak için bir komut dosyası çalıştırmak için her geliştiriciyi gerektirmediği ve kullanıcının sahip olduğu birimin dışındaki dosyaların izinleri düzeltildiğinden , bir bayrakla kapsayıcı çalıştırmaktan daha iyi bunu seviyorum .


Ayrıca, docker cihazına bağlama bağlama gerçekleştiren adlandırılmış bir birim kullanarak görüntüden bir ana bilgisayar dizini başlatmasını da sağlayabilirsiniz. Bu dizinin önceden var olması gerekir ve bir oluşturma dosyasındaki göreli yollar olabilecek ana bilgisayar birimlerinin aksine, ana bilgisayar dizinine mutlak bir yol sağlamanız gerekir. Docker'ın başlatması için dizin de boş olmalıdır. Bir bağlanan bağlama birimine adlandırılmış bir birimi tanımlamak için üç farklı seçenek aşağıdaki gibidir:

  # 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
  ...

Son olarak, kullanıcı ad alanlarını kullanmayı denerseniz, kapsayıcıların uid / gid değerleri değiştiği için ana bilgisayar birimlerinin izin sorunları olduğunu göreceksiniz. Bu senaryoda, ana bilgisayar birimlerinden kaçınmak ve yalnızca adlandırılmış birimler kullanmak en kolay yoldur.


32

Gönderen access.redhat.com:Sharing_Data_Across_Containers :

Ana makine ses düzeyi ayarları, ana bilgisayara bağlı olduğundan ve başka bir makinede çalışmayabileceğinden taşınabilir değildir. Bu nedenle, ana bilgisayar dizinlerini kaba bağlamak için Dockerfile eşdeğeri yoktur. Ayrıca, ana bilgisayar sisteminin kapsayıcı SELinux politikası hakkında hiçbir bilgisi olmadığını unutmayın. Bu nedenle, SELinux ilkesi uygulanırsa, bağlı ana bilgisayar dizini, rw ayarından bağımsız olarak kapsayıcıya yazılamaz. Şu anda, ana bilgisayar dizinine uygun SELinux ilke türünü atayarak bu sorunu çözebilirsiniz ":

chcon -Rt svirt_sandbox_file_t host_dir

Burada host_dir, konteynere monte edilmiş ana sistemdeki dizine giden bir yoldur.

Bu sadece bir çözüm gibi görünüyor, ama denedim ve işe yarıyor.


14

Bunun chcon -Rt svirt_sandbox_file_t /path/to/volumeişe yaradığını doğruladım ve ayrıcalıklı bir kapsayıcı olarak çalıştırmanız gerekmiyor.

Bu açık:

  • Docker sürümü 0.11.1-dev, yapı 02d20af / 0.11.1
  • SELinux etkin ana ve kapsayıcı olarak CentOS 7.

2
Docker içinde yeniden etiketleme için resmi destek için github.com/docker/docker/pull/5910 adresine bakın .
cpuguy83

13

Deneyin 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/ belgesine bir göz atın.


3
SO hakkında bu konuda birçok cevap denedim, ama aslında bu yardımcı oldu. Teşekkürler!
Paul

İzin hatasını çözdü.Ama şimdi fiziksel konumu monte etmeye çalışıyorsam voulme bağlıyor ???? @ cupen
verma

1
@kunalverma Evet. Eğer beğenmezseniz, işte daha kolay cevap. stackoverflow.com/a/31334443/4909388
cupen

4

Benzer bir sorunum vardı, benimki, ana bilgisayarın UID'si ve kabın kullanıcısının UID'si arasındaki bir uyumsuzluktan kaynaklandı. Düzeltme, docker yapısına bir argüman olarak kullanıcının UID'sini iletmek ve aynı UID ile kabın kullanıcısını oluşturmaktı.

DockerFile dosyasında:

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

İnşa adımında:

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

Bundan sonra, konteyneri ve komutları OP'ye göre çalıştırmak bana beklenen sonucu verdi.


1
Çalışma zamanına kadar UID'yi bilmiyorsanız ne olur? (Dosya sistemlerine yazılan bazı araçları paketlemek için iş arkadaşları için bir görüntü oluşturuyorum, ancak farklı UID'leri var). Ben kök ve sadece adduser çalıştırmak tutmak olabilir sanırım?
inger

Maalesef buna iyi bir cevabım yok. Başkasının bir çözümü varsa, ben de ilgilenirim. Docker giriş noktası işlevinin bir çözüm sağlayabileceğinden şüpheleniyorum.
RoboCop87

0

Bir veri kabı kullanarak bu sorunu çözdüm, bu da veriyi uygulama katmanından izole etme avantajına sahiptir. Bu şekilde çalıştırabilirsiniz:

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

Bu öğretici veri kapsayıcılarının kullanımı hakkında iyi bir açıklama sağlar.


-1

Benim durumumda sorun farklıydı. Nedenini bilmiyorum, ancak ana bilgisayardaki dizin üzerinde chmod 777çalıştırılmış olsa bile , docker içinde görünür 755.

Konteyner içinde çalışan sudo chmod 777 my_volume_dir onu düzeltti.


5
chmod 777neredeyse hiçbir şeyi düzeltmez.
Erki Aring

Üzgünüm, ama noktayı kaçırdınız. Mesele şu ki, konteyner içi ayrıcalıkları düşürüldü ve dışarıdan düzeltilemedi.
CodeSandwich

-2

sudo -s MAC benim için hile yaptı


1
Eğer aşağı oy veriyorsanız, bir yorum bırakın ve nedenini açıklayın. Aynı sorunla karşılaştım ve bunu sudo -s ile çözebildim.
Nachiket Joshi

Her docker görüntüsünde sudo yoktur ve her senaryoda mümkün değildir.
SOFe

2
Sudo'u kaplara kurmayın. Saldırgan sudo'yu bir kabın içinde kullanabilir.
Arnold Balliu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.