У меня есть каталог с разрешениями для пользователя user1:
$ ls -la owned-by-u1
drwxr-xr-x 19 u1 u1 4096 Sep 4 16:22 owned-by-u1
$ ls -nla
drwx------ 19 1001 1001 4096 Sep 4 16:22 owned-by-u1
когда я сопоставляю этот каталог как том с контейнером postgres, он меняет владельца каталога на идентификатор пользователя 999, который может сопоставляться с разными именами пользователей.
$ ls -la owned-by-u1
drwx------ 19 gitlab-runner u1 4096 Sep 4 16:22 owned-by-u1
$ ls -nla
drwx------ 19 999 1001 4096 Sep 4 16:22 owned-by-u1
Я запускаю контейнер вот так
docker run -d \
--name aaa-postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-e PGDATA=/var/lib/postgresql/pgdata \
-v /home/u1/tt/owned-by-u1:/var/lib/postgresql/pgdata \
postgres
Может кто-нибудь объяснить механизм, пожалуйста?
Dockerd работает от имени пользователя root (не без root), и переназначение UID не заблокировано.
Если я включу переназначение uid, контейнер выйдет из строя:
chmod: changing permissions of '/var/lib/postgresql/pgdata': Operation not permitted
find: ‘/var/lib/postgresql/pgdata’: Permission denied
chown: changing ownership of '/var/lib/postgresql/pgdata': Operation not permitted
Это ожидаемо, поскольку корень внутри не является настоящим корнем:
$ docker run \
--name aaa-postgres \
--entrypoint "" \
-e POSTGRES_PASSWORD=mysecretpassword \
-e PGDATA=/var/lib/postgresql/pgdata \
-v /home/max/tt/owned-by-u1:/var/lib/postgresql/pgdata \
postgres cat /proc/self/uid_map
дает это
0 296608 65536
что соответствует /etc/subuid:
$ cat /etc/subuid
dockremap:296608:65536
Вот немного информации о докере:
$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
desktop-linux Docker Desktop npipe:////./pipe/dockerDesktopLinuxEngine
$ docker version
Client: Docker Engine - Community
Server: Docker Engine - Community
Какова ваша среда Docker (обычный Docker в родном Linux, Docker Desktop или что-то еще)? Используете ли вы режим без рута и включили ли вы переназначение uid?
@ДэвидМейз. спасибо за ваши разъяснения, я добавил эти детали в вопрос
@JoachimSauer, да, но они разные, и это меня смущает. Я вижу, что постгресс-изображение создаёт пользователя 999, может это как-то влияет на результат?
Просто чтобы прояснить: «uid» — это числовой идентификатор пользователя, а не имя пользователя. Попробуйте перечислить файлы, используя ls -nla
.
@JoachimSauer, да, верно, я обновил вопрос выводом ls -nla
Я включил переназначение uid, и контейнер разбился, потому что не смог chown
. Думаю, до переназначения он работал как root
UID при монтировании томов между контейнером докера и хостом не сопоставляется. Но имена пользователей на обоих контролируются файлами /etc/passwd
и /etc/group
, которые специфичны для хоста и контейнера (поэтому имя пользователя на хосте не будет совпадать с именем пользователя для того же uid внутри контейнера).
В режиме без root-доступа и пространствах имен пользователей контейнеры могут сопоставлять идентификаторы пользователей и групп (после сопоставлений /etc/subuid
и /etc/subgid
и указанного пользователя с механизмом Docker). Когда контейнеры uid и gid сдвинуты, эти сдвинутые uid и gid появятся в процессах на хосте и у пользователя, пытающегося получить доступ к любым привязкам. В этом сценарии root в контейнере не является rootом на хосте, поэтому операции файловой системы, пытающиеся изменить владельца файла на хосте, завершатся неудачей так же, как если бы вы попытались запустить их от имени случайного пользователя с большим номером вне контейнера. . Если файл на хосте принадлежит uid и gid за пределами сопоставленных диапазонов, я считаю, что в контейнере он отображается как никто, и любая попытка изменить файл потерпит неудачу, поскольку пользователь контейнера не имеет доступа.
В примере postgres
он настроен на запуск от имени пользователя root и изменение прав доступа к файлам как часть точки входа. Вам следует избегать монтирования хоста/привязки и вместо этого использовать именованный том для этого сценария. Вы можете увидеть команды chown
для пользователя postgres
в /usr/local/bin/docker-entrypoint.sh
, а также текущего пользователя и пользователя postgres внутри контейнера с помощью:
# id
uid=0(root) gid=0(root) groups=0(root)
# id postgres
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
Обратите внимание, что в Docker Desktop есть виртуальная машина, внутри которой работает механизм Docker, и эта виртуальная машина имеет драйвер файловой системы, монтирующий файловые системы хоста в виртуальную машину таким образом, что автоматически сопоставляет uid и gid пользователю хоста при записи файлов, чтобы избежать проблемы с разрешениями.
Спасибо! Обратите внимание: в Docker Desktop есть виртуальная машина — возможно, вы знаете, похожа ли она на виртуальную машину фейерверка?
и, возможно, вы знаете, почему переназначение uid по умолчанию не включено в демоне Docker?
Docker Desktop основан на linuxkit, но сам код Desktop не является открытым исходным кодом (никогда не был). Включение пространств имен пользователей нарушает монтирование хостов, поэтому изменение этого значения по умолчанию приведет к нарушению существующих рабочих процессов пользователей.
ты занимаешься консалтингом? нам может понадобиться помощь эксперта
По умолчанию uid будут просто одинаковыми (хотя в некоторых настройках, таких как докер без root-прав, происходит некоторое сопоставление): uid, который вы видите в контейнере, такой же, как uid снаружи. Поскольку хост и контейнер не используют общую базу данных пользователей (т. е. /etc/passwd или что-то еще, настроенное), которая может сопоставляться с разными (или нет) пользователями.