Как мне смонтировать private /proc внутри пространства имен внутри контейнера docker?

У меня есть необходимость создать пространства имен внутри контейнера Docker. И как часть этого, мне нужно будет установить /proc закрытый для внутреннего пространства имен. Я понимаю, что мне придется запустить контейнер с определенными привилегиями, чтобы это произошло, но я бы предпочел включить самый минимальный набор.

Это работает:

$ sudo docker run --privileged --security-opt=seccomp=unconfined \ -it fedora:rawhide /usr/bin/unshare -Ufmp -r \ /bin/sh -c 'mount -t proc proc /proc'

Это не значит:

$ sudo docker run --cap-add=sys_admin --security-opt=seccomp=unconfined \  -it fedora:rawhide /usr/bin/unshare -Ufmp -r \   /bin/sh -c 'mount -t proc proc /proc'mount: /proc: cannot mount proc read-only.

Итак, просто отключите фильтры seccomp и добавьте CAP_SYS_ADMIN этого недостаточно. Что является достаточно?

Обновление: Selinux - это часть проблемы. Если вы отключите принудительное применение selinux глобально, это сработает. Но вы также можете отключить принудительное применение для конкретного контейнера с помощью --security-opt label:disable, и это задокументировано в раздел настройки безопасности в онлайн-руководстве Docker:

sudo docker run --cap-add=sys_admin --security-opt label:disable \ -it fedora:rawhide /usr/bin/unshare -fmp /bin/sh -c \ 'mount --make-private / ; mount -t proc proc /proc'

Но это терпит неудачу, если -U и -r флаги добавляются обратно в unshare. И, конечно же, добавление --privileged к команде docker run работает просто отлично, даже с -U и -r флаги.

В настоящее время я пытаюсь использовать трассировку ядра, чтобы выяснить, что именно дает мне EPERM. Это очень бесполезная неспецифическая ошибка, которую можно получить.

Эта команда работает:

sudo docker run --cap-add=sys_admin --security-opt label:disable -it fedora:rawhide /bin/sh -c 'for dir in $(awk '"'"'/\/proc\// { print $5; }'"'"' /proc/1/mountinfo ); do umount "$dir"; done; /usr/bin/unshare -Ufmp -r /bin/sh -c '"'"'mount --make-private / ; mount -t proc proc /proc ; ls /proc'"'"

Я не разделил его на несколько строк, потому что цитирование действительно важно. По сути, он размонтирует целую кучу вещей в /proc перед запуском разделите и установите /proc в пространстве имен дочернего пользователя.

Docker монтируется поверх множества каталогов и файлов в /proc со своими собственными каталогами, которые являются пустыми каталогами tmpfs и пустыми файлами. Различные файлы в /proc представляют значения, применимые ко всей системе. На самом деле, /proc/kcore это позволило бы вам читать память ядра внутри контейнера, если бы вы были root, что, поскольку многие люди хотят верить, что контейнеры - это своего рода облегченная виртуальная машина или что-то в этом роде, удивило бы многих людей.

Ядро в (во всяком случае, начиная с версии 4.14) fs/namespace.c:mnt_already_visible проверяет, монтируете ли вы уже смонтированную файловую систему, и если в этой файловой системе есть объекты, смонтированные как дочерние файловые системы, и у этих подключений есть флаг MNT_LOCKED, происходит сбой. Флаг MNT_LOCKED, похоже, применяется (я не выяснял, где он находится в ядре) ко всем монтированиям всякий раз, когда вы создаете пространство имен пользователя, чтобы предотвратить размонтирование объектов в этом пространстве имен (потому что вы получаете привилегии "внутри" пространства имен пользователя) и снова делаете скрытые объекты видимыми.

Команда, которую я опубликовал, использует awk-скрипт для содержимого /proc/1/mountinfo чтобы извлечь все подкаталоги и файлы в /proc этот докер смонтировал и размонтировал их все. Это делает /proc файловая система снова монтируется во вложенных пользовательских пространствах имен.

SamYaple на канале #docker на Freenode был здесь очень полезен, и это может быть проблемой cgroups. Похоже, что существует группа “устройства”.

Это вам не поможет, но TBH: я * действительно * удивлен, что это не стандартная опция “монтирования”, поскольку мне это кажется довольно распространенным требованием. Мне это нужно :slight_smile: … Я запускаю один двоичный файл и включаю все его библиотеки, поэтому в контейнере нет необходимости в base-O / S - так что у меня его нет, но, похоже, для некоторых функций требуется “/ proc”. То же самое произошло бы со статическими двоичными файлами, такими как “Go” - они могут быть установлены без базового ввода-вывода в контейнере. Я попробовал -v / proc: / proc, и это не помогло по той причине, которую вы указали.

вы пробовали использовать -v /proc:/proc ?

@c4f4t0r - Ну, это не сделало бы того, чего я хочу. Я не хочу, чтобы /proc из пространства имен, в котором работает docker (предположительно, пространство имен корневого уровня).

@c4f4t0r - Используя ftrace, исходные коды ядра и немного творческого мышления, я разобрался в проблеме. security - How do I mount a private /proc inside a namespace inside a docker container? - Server Fault