W dockerze pliki utworzone w kontenerach mają zazwyczaj nieprzewidywalną własność podczas sprawdzania ich z hosta. Właścicielem plików na woluminie jest domyślnie root (identyfikator UID 0), ale gdy tylko konta użytkowników innych niż root są zaangażowane w kontenerze i zapisują w systemie plików, właściciele stają się mniej lub bardziej losowi z punktu widzenia hosta.
Jest to problem, gdy trzeba uzyskać dostęp do danych woluminu z hosta przy użyciu tego samego konta użytkownika, które wywołuje polecenia dockera.
Typowe obejścia to
- wymuszanie identyfikatorów użytkowników podczas ich tworzenia w plikach Dockerfiles (nieprzenośnych)
- przekazanie identyfikatora UID użytkownika hosta do
docker run
polecenia jako zmiennej środowiskowej, a następnie uruchomienie niektórychchown
poleceń na woluminach w skrypcie punktu wejścia.
Oba te rozwiązania mogą zapewnić pewną kontrolę nad rzeczywistymi uprawnieniami poza kontenerem.
Spodziewałem się, że ostatecznym rozwiązaniem tego problemu będą przestrzenie nazw użytkowników. Przeprowadziłem kilka testów z niedawno wydaną wersją 1.10 i opcją --userns-remap ustawioną na moje konto na komputerze. Nie jestem jednak pewien, czy może to ułatwić uporanie się z własnością plików na zamontowanych woluminach, obawiam się, że w rzeczywistości może być odwrotnie.
Załóżmy, że uruchomię ten podstawowy kontener
docker run -ti -v /data debian:jessie /bin/bash
echo 'hello' > /data/test.txt
exit
A następnie sprawdź zawartość od hosta:
ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/
-rw-r--r-- 1 100000 100000 6 Feb 8 19:43 test.txt
Ten numer „100000” jest pod-UID mojego użytkownika hosta, ale ponieważ nie odpowiada on identyfikatorowi mojego użytkownika, nadal nie mogę edytować pliku test.txt bez uprawnień. Ten użytkownik podrzędny nie wydaje się mieć żadnego powiązania z moim rzeczywistym zwykłym użytkownikiem poza platformą docker. Nie jest odwzorowany.
Obejścia wspomniane wcześniej w tym poście, które polegały na wyrównywaniu identyfikatorów UID między hostem a kontenerem, nie działają już z powodu UID->sub-UID
mapowania występującego w przestrzeni nazw.
W takim razie, czy istnieje sposób na uruchomienie dockera z włączoną przestrzenią nazw użytkownika (w celu zwiększenia bezpieczeństwa), jednocześnie umożliwiając użytkownikowi hosta z uruchomionym dockerem posiadanie plików wygenerowanych na woluminach?
Odpowiedzi:
Jeśli możesz wcześniej ustawić użytkowników i grupy, można przypisać identyfikatory UID i GID w tak specyficzny sposób, aby użytkownicy hosta odpowiadali użytkownikom w przestrzeni nazw wewnątrz kontenerów.
Oto przykład (Ubuntu 14.04, Docker 1.10):
Utwórz użytkowników ze stałymi identyfikatorami numerycznymi:
Ręcznie edytuj automatycznie generowane zakresy identyfikatorów podrzędnych w plikach
/etc/subuid
i/etc/subgid
:(uwaga, nie ma zapisów dla
ns1-root
i zns1-user1
powoduMAX_UID
iMAX_GID
ograniczeń/etc/login.defs
)Włącz przestrzenie nazw użytkowników w
/etc/default/docker
:Zrestartuj demona
service docker restart
, upewnij się, że/var/lib/docker/500000.500000
katalog został utworzony.Teraz masz pojemniki wewnątrz
root
iuser1
, i na komputerze -ns1-root
ins1-user1
, z pasującymi identyfikatoramiUPDATE: aby zagwarantować, że użytkownicy inni niż root mają stałe identyfikatory w kontenerach (np. User1 1000: 1000), utwórz je jawnie podczas budowania obrazu.
Jazda testowa:
Przygotuj katalog woluminu
Wypróbuj z pojemnika
Spróbuj od gospodarza
Nie przenośny i wygląda jak hack, ale działa.
źródło
subUID lower bound + UID in image
taka, jeśli uruchamiamy wiele różnych obrazów z użytkownikiem o identyfikatorze ustawionym na 1000?Jednym ze sposobów obejścia tego problemu jest dynamiczne przypisywanie identyfikatora użytkownika w czasie kompilacji w celu dopasowania do hosta.
Przykład
Dockerfile
:Następnie zbuduj jako:
i działaj jako:
Jeśli masz istniejący kontener, utwórz kontener opakowujący zawierający
Dockerfile
:Można to zawinąć w
docker-compose.yml
:Następnie skompiluj i uruchom jako:
źródło
Możesz uniknąć problemów z uprawnieniami, używając
docker cp
polecenia .Oto przykład przełączony do użycia
docker cp
:Jeśli jednak chcesz tylko odczytać pliki z kontenera, nie potrzebujesz nazwanego woluminu. Ten przykład używa nazwanego kontenera zamiast nazwanego woluminu:
Uważam, że nazwane woluminy są przydatne, gdy chcę skopiować pliki do kontenera, jak opisano w tym pytaniu .
źródło
docker cp
wiąże się z powielaniem danych. Co więcej, zgodnie z dokumentem, podczas kopiowania danych do kontenera ustawia identyfikatory własności według użytkownika root, który często nie jest kontem, na którym działa aplikacja kontenerowa. Nie widzę, jak to rozwiązuje nasz problem.docker cp
daje Ci pełną kontrolę nad własnością pliku podczas przesyłania strumieniowego archiwum tar do kontenera lub z niego. Możesz dostosować własność i uprawnienia każdego wpisu w pliku tar podczas przesyłania strumieniowego, więc nie jesteś ograniczony do użytkownika root.