You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gVisor's overlayfs rejects a mount that uses relative lowerdir paths. On Linux, the kernel resolves those paths against the working directory of the calling process. The mount succeeds.
Expected: the mount succeeds. Observed: mount(2) returns EINVAL.
Docker 29 triggers the rejection on images with many layers. containerd switches to relative lowerdir paths after a chdir once the absolute option string would pass one page. Shallow images therefore work and deep ones fail:
failed to mount /tmp/containerd-mount3312412956: mount source: "overlay",
target: "/tmp/containerd-mount3312412956", fstype: overlay, flags: 0,
data: "workdir=/var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.overlayfs/snapshots/60/work,
upperdir=/var/lib/docker/containerd/daemon/io.containerd.snapshotter.v1.overlayfs/snapshots/60/fs,
lowerdir=59/fs:58/fs:57/fs:56/fs:51/fs:...:13/fs", err: invalid argument
A tmpfs is already mounted at /var/lib/docker, so this is a different failure from #12475.
With the default --data-root, images of about 38 layers or more fail. Those images neither run nor build. docker create paketobuildpacks/builder-jammy-java-tiny fails at 39 layers. That image is the default builder for Cloud Native Buildpacks. pack build and Spring Boot's bootBuildImage therefore do not work under gVisor.
Steps to reproduce
Run this inside a sandbox. Docker is not needed.
mkdir -p /t/rel &&cd /t/rel
mkdir -p l0 l1 u w m
# Relative lowerdir paths. Fails.
mount -t overlay overlay -o lowerdir=l0:l1,upperdir=u,workdir=w m
# mount: mounting overlay on m failed: Invalid argument# The same mount with absolute paths. Succeeds.
mount -t overlay overlay -o lowerdir=/t/rel/l0:/t/rel/l1,upperdir=/t/rel/u,workdir=/t/rel/w /t/rel/m
To separate layer count from path length, I called mount(2) directly on a tmpfs and varied each:
lower layers
paths
option string
result
80
absolute, short
749 B
mounts
40
absolute, long
3119 B
mounts
60
absolute, long
4599 B
ENAMETOOLONG
10
relative
about 100 B
EINVAL
The number of lower layers does not cause the failure. The one-page limit on the option string behaves as it does on Linux. Only relative lowerdir paths fail.
I verified two workarounds. Both are Docker-specific, and both avoid relative lowerdir paths rather than fix the mount. The chdir behaviour lives in containerd's mount helper, so other containerd consumers inside a sandbox are still affected.
A shorter --data-root keeps the absolute string under a page for longer. The limit rises by a few layers.
--feature containerd-snapshotter=false moves Docker off the containerd snapshotter entirely. The classic overlay2 driver keeps a symlink index at <root>/l/<id>, so its option string stays short. The same 39-layer image then creates successfully. Docker in gVisor: docker v29 fails to mount overlayfs #12475 recommends this flag for other Docker 29 problems. It is not a durable answer: Docker documents overlay2 as "a legacy storage driver that is superseded by the overlayfs containerd snapshotter".
runsc version
GKE Sandbox manages runsc. The node does not expose its version.
docker version (if using docker)
Docker Engine 29.7.2, in a Docker-in-Docker sidecar. It starts with --iptables=false --ip6tables=false and a tmpfs at /var/lib/docker.
uname
/proc/version reports Linux version 4.19.0-gvisor.
Description
gVisor's overlayfs rejects a mount that uses relative
lowerdirpaths. On Linux, the kernel resolves those paths against the working directory of the calling process. The mount succeeds.Expected: the mount succeeds. Observed:
mount(2)returnsEINVAL.Docker 29 triggers the rejection on images with many layers. containerd switches to relative
lowerdirpaths after a chdir once the absolute option string would pass one page. Shallow images therefore work and deep ones fail:A tmpfs is already mounted at
/var/lib/docker, so this is a different failure from #12475.With the default
--data-root, images of about 38 layers or more fail. Those images neither run nor build.docker create paketobuildpacks/builder-jammy-java-tinyfails at 39 layers. That image is the default builder for Cloud Native Buildpacks.pack buildand Spring Boot'sbootBuildImagetherefore do not work under gVisor.Steps to reproduce
Run this inside a sandbox. Docker is not needed.
To separate layer count from path length, I called
mount(2)directly on a tmpfs and varied each:ENAMETOOLONGEINVALThe number of lower layers does not cause the failure. The one-page limit on the option string behaves as it does on Linux. Only relative
lowerdirpaths fail.I verified two workarounds. Both are Docker-specific, and both avoid relative
lowerdirpaths rather than fix the mount. The chdir behaviour lives in containerd's mount helper, so other containerd consumers inside a sandbox are still affected.--data-rootkeeps the absolute string under a page for longer. The limit rises by a few layers.--feature containerd-snapshotter=falsemoves Docker off the containerd snapshotter entirely. The classicoverlay2driver keeps a symlink index at<root>/l/<id>, so its option string stays short. The same 39-layer image then creates successfully. Docker in gVisor: docker v29 fails to mount overlayfs #12475 recommends this flag for other Docker 29 problems. It is not a durable answer: Docker documentsoverlay2as "a legacy storage driver that is superseded by theoverlayfscontainerd snapshotter".runsc version
GKE Sandbox manages runsc. The node does not expose its version.
docker version (if using docker)
Docker Engine 29.7.2, in a Docker-in-Docker sidecar. It starts with
--iptables=false --ip6tables=falseand a tmpfs at/var/lib/docker.uname
/proc/versionreportsLinux version 4.19.0-gvisor.kubectl (if using Kubernetes)
GKE 1.36.3-gke.1537000. Node pool:
imageType COS_CONTAINERD,sandboxConfig.type GVISOR.