Понимание владения файлами пользователя в docker: как избежать изменения разрешений связанных томов


рассмотрим следующий тривиальный Dockerfile:

FROM debian:testing
RUN  adduser --disabled-password --gecos '' docker
RUN  adduser --disabled-password --gecos '' bob 

в рабочем каталоге ни с чем другим. Создайте изображение docker:

docker build -t test .

и затем запустить bash-скрипт на контейнер, связывающий рабочую директорию в новый подкаталог домашнего каталога на Боба:

docker run --rm -it -v $(pwd):/home/bob/subdir test 

кому принадлежит содержимое subdir на контейнере? На контейнере запустите:

cd /home/bob/subdir
ls -l

объявление мы видим:

-rw-rw-r-- 1 docker docker 120 Oct 22 03:47 Dockerfile

Святые угодники! docker владеет содержание! Вернувшись на главную машину вне контейнера, мы видим, что наш исходный пользователь все еще владеет Dockerfile. Давайте попробуем исправить право собственности на bobдомашний каталог. На контейнере запустите:

chown -R bob:bob /home/bob
ls -l 

и видим:

-rw-rw-r-- 1 bob bob 120 Oct 22 03:47 Dockerfile

но подождите! вне контейнера, мы теперь бежим ls -l

-rw-rw-r-- 1 1001 1001 120 Oct 21 20:47 Dockerfile

у нас больше нет собственного файла. Ужасные новости!


если бы мы добавили только одного пользователя в приведенном выше примере, все прошло бы более гладко. По какой-то причине Docker, похоже, делает любой домашний каталог, принадлежащий первый некорневой пользователь, с которым он сталкивается (даже если этот пользователь объявлен на более раннем изображении). Аналогично, это первый пользователь-это тот, который соответствует тем же разрешениям владения, что и мой домашний пользователь.

Вопрос 1 это правильно? Может ли кто-нибудь указать мне на документацию об этом, я просто предполагаю, основываясь на выше эксперимента.

Вопрос 2: возможно, это просто потому, что они оба имеют одинаковое числовое значение на ядре, и если бы я тестировал на системе, где мой домашний пользователь не был id 1000 тогда разрешения будут изменены в каждом случае?

Вопрос 3: вопрос, конечно, что мне делать по этому поводу?- Если bob вошел в bob на данном хост-компьютере он должен иметь возможность запускать контейнер как bob и не имеют прав доступа к файлам, измененных под его учетной записью хоста. Как бы то ни было, он на самом деле должен запустить контейнер как пользователь docker чтобы избежать изменения его учетной записи.

2 52

2 ответа:

это правильно? Может ли кто-нибудь указать мне на документацию об этом, я просто предполагаю, основываясь на приведенном выше эксперименте.

возможно, это просто потому, что они оба имеют одинаковое числовое значение на ядре, и если бы я тестировал в системе, где мой домашний пользователь не был id 1000, то разрешения менялись бы в каждом случае?

прочитать info coreutils 'chown invocation', это может дать вам лучшее представление о том, как права доступа к файлам / владение завод.

в основном, однако, каждый файл на вашем компьютере имеет набор битов, прикрепленных к нему, который определяет его разрешения и права собственности. Когда ты chown файл, вы просто устанавливаете эти биты.

когда вы chown файл для конкретного пользователя/группы, используя имя пользователя или имя группы, chown будет выглядеть в /etc/passwd имя пользователя и /etc/group для группы, чтобы попытаться сопоставить имя с идентификатором. Если имя пользователя / группы не существует в этих файлах, chown будет неудача.

root@dc3070f25a13:/test# touch test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 root root    0 Oct 22 18:15 test
root@dc3070f25a13:/test# chown test:test test
chown: invalid user: 'test:test'

однако, вы можете chown файл, использующий идентификаторы для всего, что вы хотите (в пределах некоторых верхних положительных целочисленных границ, конечно), есть ли пользователь / группа, которая существует с этими идентификаторами на вашем компьютере или нет.

root@dc3070f25a13:/test# chown 5000:5000 test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 5000 5000    0 Oct 22 18:15 test

биты UID и GID устанавливаются в самом файле, поэтому при монтировании этих файлов внутри контейнера docker файл имеет тот же идентификатор владельца / группы, что и на хосте, но теперь сопоставляется с /etc/passwd в контейнере, который вероятно, будет другой пользователь, если он не принадлежит root (UID 0).

реальный вопрос, конечно, что мне делать по этому поводу?"Если Боб вошел в систему как боб на данном хост-компьютере, он должен иметь возможность запускать контейнер как Боб и не иметь прав доступа к файлам, измененных под его учетной записью хоста. Как бы то ни было, ему действительно нужно запустить контейнер в качестве пользователя docker, чтобы избежать изменения его учетной записи.

похоже, с вашим нынешним настройка, вам нужно будет убедиться, что ваши UIDs > имена пользователей в /etc/passwd на вашем хосте совпадают с вашими UIDs > имена пользователей в ваших контейнерах /etc/passwd если вы хотите взаимодействовать с подключенным каталогом пользователя как тот же пользователь, который вошел в систему на хосте.

вы можете создать пользователя с определенным идентификатором пользователя с useradd -u xxxx. Buuuut, это действительно похоже на грязное решение...

возможно, вам придется придумать решение, которое не монтирует домашний каталог пользователей хоста.

два варианта я нашел:

CHOWN все вещи (после выполнения вашей работы)

Я сделал docker run -v `pwd`/shared:/shared image, и контейнер создал файлы в пределах pwd/shared, которые, как владельцем процесса докер. Однако,/shared все еще принадлежит мне. Поэтому в процессе докера я делаю

chown -R `stat -c "%u:%g" /shared` /shared

stat -c "%u:%g" /shared возвращает 1000:1000 в моем случае, являясь uid:gid моего пользователя. Даже если нет пользователя 1000 в докере conatainer, идентификатор есть ли (и stat /shared просто говорит "неизвестно", если вы спросите имя пользователя).

во всяком случае,chown послушно передает право собственности на содержание /shared до 1000:1000 (который, насколько это касается, не существует, но вне контейнера, это я). Так что теперь у меня есть все файлы. Контейнер все еще может изменять вещи, если захочет, потому что с его точки зрения это root.

и все хорошо с миром.

docker run -u итак, все файлы созданы автоматически будет иметь право владельца

другой способ сделать это -u флаг при запуске докера.

docker run -v `pwd`/shared:/shared -u `stat -c "%u:%g" /shared` ubuntu bash

таким образом, пользователь docker внутри контейнера является youruid:yourgid.

: это означает отказ от ваших корневых полномочий в контейнере (apt-get install и т. д.). Если вы не создадите пользователя с этим новым uid и не добавите его в root группы.