Zazwyczaj problemy z uprawnieniami do montowania woluminu hosta są spowodowane tym, że identyfikator UID / GID w kontenerze nie ma dostępu do pliku zgodnie z uprawnieniami UID / GID pliku na hoście. Jednak ten konkretny przypadek jest inny.
Kropka na końcu ciągu uprawnień drwxr-xr-x.
wskazuje, że SELinux jest skonfigurowany. Gdy używasz montowania hosta w SELinux, musisz przekazać dodatkową opcję na końcu definicji woluminu:
- Ta
z
opcja wskazuje, że zawartość podłączenia wiązania jest współużytkowana przez wiele kontenerów.
- Ta
Z
opcja wskazuje, że treść podłączenia powiązania jest prywatna i nieudostępniona.
Polecenie podłączenia woluminu wyglądałoby wtedy następująco:
sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash
Więcej informacji o podłączeniach hosta za pomocą SELinuksa można znaleźć na stronie : https://docs.docker.com/storage/#configure-the-selinux-label
W przypadku innych, którzy widzą ten problem z kontenerami działającymi jako inny użytkownik, musisz upewnić się, że identyfikator użytkownika / identyfikator użytkownika w kontenerze ma uprawnienia do pliku na hoście. Na serwerach produkcyjnych jest to często wykonywane przez kontrolowanie identyfikatora UID / GID w procesie kompilacji obrazu, aby dopasować identyfikator UID / GID na hoście, który ma dostęp do plików (lub jeszcze lepiej, nie używaj montowań hosta w produkcji).
Nazwany wolumin jest często preferowany zamiast montowania hosta, ponieważ zainicjuje on katalog woluminów z katalogu obrazów, w tym wszelkie prawa własności i uprawnienia do plików. Dzieje się tak, gdy wolumin jest pusty i kontener jest tworzony z nazwanym woluminem.
Użytkownicy systemu MacOS mają teraz system OSXFS, który automatycznie obsługuje identyfikatory uid / gid między hostem Mac a kontenerami. Jednym z miejsc, w którym nie pomaga, są pliki z wbudowanej maszyny wirtualnej, które są montowane w kontenerze, takie jak /var/lib/docker.sock.
W środowiskach programistycznych, w których identyfikator uid / gid hosta może się zmieniać w zależności od programisty, moim preferowanym rozwiązaniem jest uruchomienie kontenera z punktem wejścia działającym jako root, poprawienie identyfikatora uid / gid użytkownika w kontenerze, aby pasowało do identyfikatora uid / gid woluminu hosta, i następnie użyj, gosu
aby upuścić z katalogu głównego do użytkownika kontenera, aby uruchomić aplikację w kontenerze. Ważny skrypt do tego znajduje się fix-perms
w moich podstawowych skryptach graficznych, które można znaleźć na stronie : https://github.com/sudo-bmitch/docker-base
Ważnym fragmentem fix-perms
skryptu jest:
# 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
To dostaje identyfikator użytkownika w kontenerze i identyfikator pliku, a jeśli się nie zgadzają, wzywa usermod
do dostosowania identyfikatora użytkownika. Na koniec wyszukuje rekursywnie, aby naprawić pliki, które nie zmieniły identyfikatora użytkownika. Podoba mi się to bardziej niż uruchamianie kontenera z -u $(id -u):$(id -g)
flagą, ponieważ powyższy kod punktu wejścia nie wymaga od każdego programisty uruchomienia skryptu w celu uruchomienia kontenera, a wszelkie pliki poza woluminem, które są własnością użytkownika, zostaną poprawione.
Można również zlecić dokerowi zainicjowanie katalogu hosta z obrazu przy użyciu nazwanego woluminu, który wykonuje podłączenie wiązania. Ten katalog musi istnieć wcześniej i należy podać bezwzględną ścieżkę do katalogu hosta, w przeciwieństwie do woluminów hosta w pliku tworzenia, które mogą być ścieżkami względnymi. Katalog musi być również pusty, aby doker mógł go zainicjować. Wyglądają trzy różne opcje definiowania nazwanego woluminu dla montowania wiązania:
# 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
...
Na koniec, jeśli spróbujesz użyć przestrzeni nazw użytkownika, okaże się, że woluminy hosta mają problemy z uprawnieniami, ponieważ uid / gid kontenerów są przesunięte. W tym scenariuszu prawdopodobnie najłatwiej jest uniknąć woluminów hosta i używać tylko woluminów nazwanych.