What this error means
Docker’s overlay2 storage driver mounts an overlay filesystem to assemble container layers. The error “error creating overlay mount: operation not permitted” indicates the kernel refused the mount. Common causes:
- Rootless Docker using overlay2 without fuse-overlayfs support
- Docker-in-Docker (dind) without enough privileges
- Kernel overlay module missing or disallowed in user namespaces
- SELinux/AppArmor policy blocking mounts
- Backing filesystem incompatibility (e.g., XFS without ftype=1, network filesystems)
- WSL1 or old kernels lacking overlayfs support
Quickstart fixes
- Rootless Docker: install fuse-overlayfs and set storage-driver=fuse-overlayfs.
- Docker-in-Docker: run the daemon container with --privileged, or use the vfs driver as a fallback.
- Kernel module: load overlay (modprobe overlay) and persist it.
- Filesystem: ensure /var/lib/docker is on ext4 or XFS with ftype=1; avoid NFS.
- SELinux: label bind mounts with :Z or :z; keep container-selinux up to date.
- Debian/Ubuntu user namespaces: enable kernel.unprivileged_userns_clone=1.
- WSL: use WSL2; WSL1 cannot mount overlayfs.
Minimal working example (rootless with fuse-overlayfs)
This example resolves the error for rootless Docker by switching to fuse-overlayfs.
# 1) Install fuse-overlayfs
# Debian/Ubuntu
sudo apt-get update && sudo apt-get install -y fuse-overlayfs uidmap
# RHEL/Fedora
# sudo dnf install -y fuse-overlayfs shadow-utils
# 2) Ensure unprivileged user namespaces are enabled (Debian/Ubuntu often needs this)
cat /proc/sys/kernel/unprivileged_userns_clone || true
# If it prints 0, enable it:
# sudo sh -c 'echo kernel.unprivileged_userns_clone=1 > /etc/sysctl.d/99-rootless.conf'
# sudo sysctl --system
# 3) Configure rootless Docker to use fuse-overlayfs
mkdir -p ~/.config/docker
cat > ~/.config/docker/daemon.json <<'JSON'
{
"storage-driver": "fuse-overlayfs"
}
JSON
# 4) Restart the rootless daemon
systemctl --user restart docker
# If not using systemd for user services, restart how you normally manage rootless docker
# 5) Verify and run a test container
docker info | grep -E 'Rootless|Storage Driver|Backing Filesystem'
docker run --rm alpine:3.20 true
Minimal Dockerfile build test:
FROM alpine:3.20
RUN echo OK > /ok && cat /ok
docker build -t overlay-ok . && docker run --rm overlay-ok
Step-by-step diagnosis and fixes
- Identify your context
- Run: docker info
- Note: Rootless: true/false, Storage Driver: overlay2/fuse-overlayfs/vfs, Backing Filesystem: ext4/xfs.
- Are you inside a container (dind) or on the host?
- Rootless Docker path
- Symptom: overlay2 fails to mount in a user namespace.
- Fix:
- Install fuse-overlayfs.
- Set storage-driver to fuse-overlayfs in ~/.config/docker/daemon.json.
- Ensure kernel.unprivileged_userns_clone=1 on Debian/Ubuntu.
- Restart the rootless daemon and test.
- Docker-in-Docker (dind)
- Symptom: docker:dind without privileges cannot perform overlay mounts.
- Fix options:
- Preferred: run privileged dind:
docker run --privileged --name dind -d -p 2375:2375 docker:24-dind - Fallback: use vfs driver (slower but works without overlay):
docker run --privileged -e DOCKER_DRIVER=vfs --name dind -d docker:24-dind
- Preferred: run privileged dind:
- Kernel overlay module
- Ensure the module is present and loaded:
lsmod | grep overlay || true sudo modprobe overlay echo overlay | sudo tee /etc/modules-load.d/overlay.conf >/dev/null - If modprobe fails, your kernel may be too old or configured without overlayfs.
- Backing filesystem compatibility
- Overlay2 requires a local Linux fs (ext4 or XFS with ftype=1). Avoid NFS/SMB/FUSE mounts for /var/lib/docker.
- Check XFS ftype:
sudo xfs_info /var/lib/docker 2>/dev/null | grep ftype || true- If ftype=0, reformat with ftype=1 or move /var/lib/docker to a suitable filesystem.
- SELinux and AppArmor
- On SELinux systems (Fedora/RHEL/CentOS), relabel bind mounts:
docker run --rm -v /host/dir:/container/dir:Z alpine ls /container/dir - Keep container-selinux updated. Avoid disabling SELinux; use proper labeling.
- For AppArmor, use the default docker profile; if you customized it, ensure mount operations needed by overlay are allowed.
- WSL notes
- WSL1 cannot mount overlayfs; use WSL2.
- Check version:
Ensure your distro is version 2 and the WSL2 kernel is up to date.wsl.exe -l -v
- Last-resort fallback
- If overlay cannot be enabled, switch Docker’s storage driver:
Note: vfs is significantly slower; use only when necessary.sudo mkdir -p /etc/docker echo '{"storage-driver": "vfs"}' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker
Performance notes
- overlay2 on ext4/XFS (ftype=1) is fastest and most space-efficient.
- fuse-overlayfs (rootless) is generally good, with minor overhead vs overlay2.
- vfs is correct but slow and disk-hungry; avoid for production CI unless required.
- Docker-in-Docker with vfs amplifies I/O; prefer privileged dind with overlay2 where permitted.
Common pitfalls
- Storing /var/lib/docker on NFS/SMB or inside another FUSE mount breaks overlay.
- XFS formatted with ftype=0 cannot support overlay2.
- Old kernels or container hosts with user namespaces disabled block rootless overlay mounts.
- Running dind without --privileged and expecting overlay2 to work.
- Ignoring SELinux labels on bind mounts leading to denials.
Tiny FAQ
Why did this start after moving /var/lib/docker?
- The new filesystem likely lacks required features (e.g., XFS ftype=1) or is a network/FUSE mount.
Is it safe to run dind with --privileged?
- It’s common in CI, but expands the container’s privileges. Restrict the environment and avoid multi-tenant exposure.
Can I fix this without root access?
- Use rootless Docker with fuse-overlayfs and ensure unprivileged user namespaces are enabled.
Does Kubernetes/containerd have the same issue?
- Yes. The snapshotter also relies on overlayfs. Rootless setups typically use fuse-overlayfs; otherwise ensure kernel support and proper filesystems.
How do I verify the fix?
- Run docker info to confirm Storage Driver and successfully build/run a small image as shown above.