Dockerfile: Mount the root `/proc/` into another directory
Description
I would like mount the /proc/ directory inside another directory.
First of all, /proc/ is not a regular directory, it's a virtual filesystem; https://docs.kernel.org/filesystems/proc.html.
Some container build scenarios require it accessible from another directory than from the root.
There are some packages that require /proc/ to exist. For example, the SUSE permissions package if using SLES. If installing this package in a non-root location, i.e. some other path than / (root), one can do that with zypper, a package manager for SLES:
zypper --non-interactive --installroot /foo/ install --no-recommends \
permissions
This seems impossible with Dockerfiles, but work fine when e.g. using something like buildah where I can mount like:
mount -t proc /proc "/foo/proc/"
Without such functionality, it is not possible to use Dockerfiles with options like zypper's --installroot. There are most likely similar options for other package managers.
(broken out from https://github.com/moby/moby/issues/47899)
I'm not sure that is something we can support; mounting requires CAP_SYS_ADMIN; see mount(2)
Appropriate privilege (Linux: the
CAP_SYS_ADMINcapability) is required to mount filesystems.
CAP_SYS_ADMIN is not part of the default set of capabilities as it provides many, many capabilities, making it a very unsafe option to provide;
Mounting fails on a container without CAP_SYS_ADMIN;
docker run -it --rm alpine sh -c 'mkdir -p /foo/proc && mount -t proc /proc "/foo/proc/" && echo success'
mount: permission denied (are you root?)
With CAP_SYS_ADMIN, this works;
docker run -it --rm --cap-add CAP_SYS_ADMIN alpine sh -c 'mkdir -p /foo/proc && mount -t proc /proc "/foo/proc/" && echo success'
success
What exactly does the permissions package do, and what are you trying to achieve?
@thaJeztah I understand that the question "what are you trying to achieve" might be go avoid the XY problem, but if we forget about that for a moment and do consider that we really have requirements to be able to install some packages dependent on /proc/, what would one do?
Just pretend I want to install permissions into a non-root path.
I have found one solution possibly. One could use https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#run---security and then something like:
zypper --non-interactive install --no-recommends \
curl \
util-linux
mkdir -p /foo/proc/
mount -t proc /proc/ /foo/proc/
zypper --non-interactive --installroot /foo/ install --no-recommends --auto-agree-with-licenses \
gawk \
hostname \
iproute2 \
rpm \
util-linux \
which \
sles-release
util-linux installs the mount command, which requires privileges.
Naturally I would want to achieve this inside a container without privileges, hence this request.
The package util-linux installs permissions.
My question was also to understand what the permissions package expects to do once the image is built, and run. If it requires CAP_SYS_ADMIN to run the image, then the image limited in portability.
In either case, as this is related to containers started during docker build, it's probably best to move this ticket to the BuildKit repository, as BuildKit is the runtime to create containers during build.
I suspect this is basically the same issue as https://bugzilla.suse.com/show_bug.cgi?id=1219736? permissions uses chkstat which uses /proc to double-check paths in /proc/self/fd/... to handle checking symlink resolutions.
I would recommend leaving a comment in that bug to let folks know that it's an issue actual customers are hitting (though in your case, my suggestions to use fsopen or mount a temporary procfs won't work because you don't have CAP_SYS_ADMIN.)
@thaJeztah I do not know what the permissions package expects to do during runtime. All I know is that it fails to install in a Dockerfile in the scenario described. @cyphar stepped in and explained why luckily.
@cyphar I believe you are right. The failure for us looks like this:
24.75 (50/50) Installing: util-linux-2.37.4-150500.9.11.1.x86_64 [....
25.77 Warning: running kernel does not support fscaps
25.77 ERROR: /proc is not available - unable to fix policy violations.
25.77 ERROR: not all operations were successful.
25.77 /usr/bin/wall should be root:tty 2755. (wrong permissions 0755)
25.77 /usr/bin/write should be root:tty 2755. (wrong permissions 0755)
25.77 Warning: running kernel does not support fscaps
25.79 done]
25.79 Running post-transaction scripts [...done]
------
Dockerfile:24
...
...
Do you know if there is any solution to this that is sensible?
With buildah one can do mount -t proc /proc "/foo/proc/". If one could do a similar mount in Dockerfiles e.g. something like RUN --mount=type=proc,from=busybox:1.35.0,source=/proc/,target=/proc/foo/ (where busybox:1.35.0 could be left out to specify the same Dockerfile as being built?) it would solve it. But I have no idea if that is feasible. And it would need to be implemented in BuildKit.
I feel waiting for a fix for https://bugzilla.suse.com/show_bug.cgi?id=1219736 might only solve that case partially, maybe there are other cases/packages that need /proc/. So fixing both that bug and a new feature for Dockerfiles might be appropriate?