Docker ve --userns-remap, ana bilgisayar ve konteyner arasında veri paylaşmak için birim izinlerini nasıl yönetebilirim?


96

Docker'da, kapsayıcılar içinde oluşturulan dosyalar ana bilgisayardan incelenirken öngörülemeyen sahipliğe sahip olma eğilimindedir. Bir birimdeki dosyaların sahibi varsayılan olarak root'tur (uid 0), ancak root olmayan kullanıcı hesapları kapsayıcıya dahil olur olmaz ve dosya sistemine yazılırsa, sahipler ana bilgisayar perspektifinden az çok rastgele hale gelir.

Docker komutlarını çağıran aynı kullanıcı hesabını kullanarak ana bilgisayardan birim verilerine erişmeniz gerektiğinde bu bir sorundur.

Tipik geçici çözümler şunlardır:

  • Dockerfiles'te oluşturma sırasında kullanıcıların uID'lerini zorlamak (taşınabilir olmayan)
  • ana bilgisayar kullanıcısının UID'sini docker runbir ortam değişkeni olarak komuta geçirmek ve ardından bir giriş noktası komut chowndizisindeki birimler üzerinde bazı komutları çalıştırmak .

Her iki çözüm de kapsayıcı dışındaki gerçek izinler üzerinde bir miktar kontrol sağlayabilir.

Kullanıcı ad alanlarının bu soruna nihai çözüm olmasını bekliyordum. Kısa süre önce yayınlanan sürüm 1.10 ve --userns-remap masaüstü hesabıma ayarlanmış olarak bazı testler çalıştırdım. Bununla birlikte, takılı birimlerde dosya sahipliğinin üstesinden gelmeyi kolaylaştıracağından emin değilim, korkarım bunun tam tersi olabilir.

Bu temel kapsayıcıyı başlattığımı varsayalım

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

Ve sonra ana bilgisayardaki içeriği inceleyin:

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

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

Bu '100000' sayısı, ana bilgisayar kullanıcımın bir alt UID'sidir, ancak kullanıcımın UID'sine karşılık gelmediği için, yine de ayrıcalıklar olmadan test.txt'yi düzenleyemiyorum. Bu alt kullanıcının docker dışındaki gerçek normal kullanıcımla herhangi bir ilgisi yok gibi görünüyor. Geriye doğru haritalanmamış.

Bu yazıda daha önce bahsedilen ve ana bilgisayar ile konteyner arasında UID'lerin hizalanmasından oluşan geçici çözümler UID->sub-UID, ad alanında gerçekleşen eşleştirme nedeniyle artık çalışmıyor .

Öyleyse, docker'ı kullanıcı ad alanı etkinken (gelişmiş güvenlik için) çalıştırmanın ve docker çalıştıran ana bilgisayar kullanıcısının ciltlerde oluşturulan dosyalara sahip olmasını sağlamanın bir yolu var mı?


Sana ev sahibi ve kullanıcı ad olduğu kap arasındaki hacimleri paylaşımı olacak eğer düşünüyorum değil çözümün bir parçası olacak. İkinci seçeneğiniz ("ana bilgisayar kullanıcısının UID'sini docker run komutuna bir ortam değişkeni olarak geçirmek ve ardından bir giriş noktası komut dosyasındaki birimler üzerinde bazı chown komutlarını çalıştırmak") muhtemelen en iyi çözümdür.
larsks

4
Docker'ın kendisi, ana bilgisayara monte yazılabilir birimleri kullanmayı teşvik etmiyor gibi görünüyor. Bir bulut hizmeti çalıştırmadığım ve yalnızca kendi güvenilir resimlerimi kullandığım için, artık NS kullanıcısının güvenlik avantajının bu kadar kolaylıktan ödün vermeye değer olup olmadığını merak ediyorum.
Stéphane C.

@Kafadergisi belki daha iyi bir yaklaşım buldunuz mu?
Seksen Sekiz

4
Ne yazık ki hayır, kullanıcı ad alanını kullanmamak ve ana bilgisayardan UID'leri iletmek hala benim tercihim. Umarım gelecekte kullanıcıları haritalandırmanın uygun bir yolu olur. Şüpheliyim ama yine de gözümü açık tutuyorum.
Stéphane C.

Yanıtlar:


46

Kullanıcıları ve grupları önceden düzenleyebiliyorsanız, UID'leri ve GID'leri o kadar özel bir şekilde atamak mümkündür, böylece ana bilgisayar kullanıcıları, kapsayıcılar içindeki ad alanlı kullanıcılara karşılık gelir.

İşte bir örnek (Ubuntu 14.04, Docker 1.10):

  1. Sabit sayısal kimliklere sahip bazı kullanıcılar oluşturun:

    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. /etc/subuidVe /etc/subgiddosyalardaki otomatik olarak oluşturulan alt kimlik aralıklarını manuel olarak düzenleyin :

    ns1:500000:65536
    

    (için ns1-rootve ns1-user1nedeniyle herhangi bir kayıt MAX_UIDve MAX_GIDsınırları olmadığını unutmayın /etc/login.defs)

  3. Kullanıcı ad alanlarını şurada etkinleştirin /etc/default/docker:

    DOCKER_OPTS="--userns-remap=ns1"
    

    Arka plan programını yeniden başlatın service docker restart, /var/lib/docker/500000.500000dizinin oluşturulduğundan emin olun .

    Şimdi, iç kaplar sahip rootve user1ve ana bilgisayarda - ns1-rootve ns1-user1eşleştirme kimlikleri ile,

    GÜNCELLEME: Root olmayan kullanıcıların kapsayıcılarda sabit kimliklere sahip olmasını garanti etmek için (örneğin, kullanıcı1 1000: 1000), bunları görüntü oluşturma sırasında açıkça oluşturun.

Test sürüşü:

  1. Bir birim dizini hazırlayın

    mkdir /vol1
    chown ns1-root:ns1-root /vol1
    
  2. Bir kaptan deneyin

    docker run --rm -ti -v /vol1:/vol1 busybox sh
    echo "Hello from container" > /vol1/file
    exit
    
  3. Ev sahibinden deneyin

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

Taşınabilir değil ve bilgisayar korsanlığı gibi görünüyor, ancak çalışıyor.


3
Çok ilginç ve + 1'i hak ediyor. Ancak yine de görüntünüzdeki user1'in UID 1000 olarak atandığından emin olmanız gerekir. Aksi takdirde, ana bilgisayarda UID 501000'i alacağından emin olamazsınız. Btw, subUID lower bound + UID in imagekimliği 1000 olarak ayarlanmış bir kullanıcıyla birçok farklı görüntü çalıştırıyorsak formülün her zaman olduğundan kesinlikle emin miyiz?
Stéphane C.

@Kafadergisi İyi bir nokta! Görüntülerin içindeki kimliklerin düzeltilmesiyle ilgili bir not eklendi. Formüle gelince, kendi resimlerimle daha fazla deney yapacağım ve bir şey
bulursa

1
Kullanıcıları ve grupları ana bilgisayarda ve kapsayıcılarda elle düzenlerseniz, gerçekten "kullanıcı ad alanı" özelliğine ihtiyacınız var mı?
Tristan

1
Oluşturduğunuz ad alanı, ana bilgisayar kullanıcılarını konteyner kullanıcılarından ayırır, ancak özellikle resmi resimler (mysql gibi) açık uid olmadan bir kullanıcı oluşturduğunda konteynerler için birden fazla ad alanına ihtiyacınız olabilir. --Userns-remap seçeneği yalnızca birini beklerken birden çok ad alanıyla nasıl başa çıkarsınız?
Tristan

2
@amartynov "ns1" kullanıcınız için neden bir UID (5000) belirleme zahmetine girdiğinizi sorabilir miyim? Subuid ve subgid dosyalarında başvurduğunuz isim (UID değil) olduğundan, bu kullanıcının aldığı UID'nin önemi yok gibi görünüyor. 5000 ile 500000 arasındaki benzerliğin önerebileceği gibi, bazı ilişkileri özlüyor muyum?
Jollymorphic

2

Bir geçici çözüm, kullanıcının kullanıcı kimliğini derleme zamanında ana bilgisayarla eşleşecek şekilde dinamik olarak atamaktır.

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

Sonra şu şekilde inşa edin:

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

ve şu şekilde çalıştırın:

docker run mycontainer

Mevcut kapsayıcınız varsa, aşağıdakilerle bir sarmalayıcı kapsayıcı oluşturun Dockerfile:

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

Bu, şu şekilde sarılabilir docker-compose.yml:

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

Ardından şu şekilde oluşturun ve çalıştırın:

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

1
Dostça görünmek istemezdim, ancak bu aslında orijinal soruda listelenen geçici çözümlerden biridir, ancak bir çözüm değildir ve kullanıcı ad alanlarıyla ilgili değildir.
Stéphane C.

@Kafadergisi Bu ilgili soruya yorum yapabilir misiniz? stackoverflow.com/questions/60274418/…
overerexchange

-1

docker cpKomutu kullanarak izin sorunlarını önleyebilirsiniz .

Sahiplik, hedefteki kullanıcı ve birincil grup olarak ayarlanır. Örneğin, bir konteynere kopyalanan dosyalar UID:GIDkök kullanıcı ile oluşturulur . Yerel makineye kopyalanan dosyalar UID:GID, docker cpkomutu çağıran kullanıcıyla oluşturulur .

Kullanılacak örneğiniz şu şekildedir 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
$ 

Ancak, dosyaları bir kapsayıcıdan okumak istiyorsanız, adlandırılmış birime ihtiyacınız yoktur. Bu örnek, adlandırılmış birim yerine adlandırılmış bir kapsayıcı kullanır:

$ 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
$ 

Bu soruda açıklandığı gibi, dosyaları bir kapsayıcıya kopyalamak istediğimde adlandırılmış birimleri yararlı buluyorum .


Ancak docker cpverilerin kopyalanmasını içerir. Ayrıca, dokümana göre, verileri bir kapsayıcıya kopyalarken sahiplik kimliklerini kök kullanıcıya göre ayarlar, bu genellikle kapsayıcıya alınmış uygulamayı çalıştıran hesap değildir. Sorunumuzu nasıl çözdüğünü göremiyorum.
Stéphane C.

Haklısın @ Stéphane, verilerin kopyalanmasını içeriyor. Bununla birlikte, dosyaların kopyalarını oluşturmak, ana bilgisayarda ve kapsayıcıda farklı sahiplik ve izinler atamanıza olanak tanır. docker cpbir kapsayıcıdan veya kapsayıcıdan bir tar arşivini akışa aldığınızda dosya sahipliği üzerinde tam kontrol sağlar. Tar dosyasındaki her girişin sahipliğini ve izinlerini akış olarak ayarlayabilir, böylece kök kullanıcıyla sınırlı kalmazsınız.
Don Kirkby
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.