The Error
failed to register layer: symlink /usr/bin/python3 /usr/bin/python: operation not permitted
error pulling image configuration: failed to register layer
It's midnight. You're pulling a Python or Node base image, and Docker dies halfway through with this cryptic message. Maybe it worked yesterday on the same machine. Maybe you just set up a fresh Windows install and are hitting this immediately. Either way, the image never finishes, and any docker build referencing it fails too.
Root Cause
The core problem: Docker must create real filesystem symlinks when extracting image layers. NTFS โ the Windows filesystem โ either doesn't support them or requires elevated privileges your WSL2 session doesn't have.
Two scenarios trigger this:
- Your project is under
/mnt/c/or/mnt/d/โ WSL2 mounts Windows drives via a 9P protocol bridge. Symlink creation through that bridge is blocked or unreliable. - Docker's data-root points to a Windows-backed path โ Docker stores image layers somewhere like
/mnt/c/Users/yourname/.docker, which can't hold Linux symlinks.
Same root cause, same fix: get everything off the NTFS mount and onto WSL2's native ext4 filesystem.
Fix 1: Move Your Project Into the WSL2 Filesystem (Fastest Fix)
Running docker build or docker pull from inside /mnt/c/? That's your problem. Copy the project to your Linux home directory:
# From inside WSL2 terminal
cp -r /mnt/c/Users/yourname/projects/myapp ~/myapp
cd ~/myapp
docker build .
Paths like ~/ and /home/yourname/ live on WSL2's internal virtual disk (ext4.vhdx). Full Linux semantics โ symlinks work fine.
This alone resolves the error for roughly 80% of cases.
Fix 2: Verify and Move Docker's Data-Root
Even with your project on the Linux filesystem, Docker storing image layers on a Windows drive produces the exact same error. Check where Docker keeps its data:
docker info | grep 'Docker Root Dir'
Output pointing to /mnt/c/... or /mnt/d/... means you need to redirect it.
For Docker Engine inside WSL2 (not Docker Desktop), edit the daemon config:
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
Add or update the data-root:
{
"data-root": "/home/yourname/.docker-data"
}
Then restart Docker:
sudo systemctl restart docker
Fix 3: Docker Desktop โ Check WSL2 Integration Settings
Docker Desktop with the WSL2 backend manages its own virtual disk. The usual culprit here is running Docker commands from a Windows-mounted path in a WSL2 terminal โ not a problem with Docker Desktop itself.
Open Docker Desktop โ Settings โ Resources โ WSL Integration. Enable the integration for your WSL2 distro (Ubuntu, Debian, etc.).
Then, inside WSL2, confirm Docker's root is on the virtual disk:
docker info | grep 'Docker Root Dir'
# Should show: Docker Root Dir: /var/lib/docker
Seeing /var/lib/docker? The data-root is fine โ your build context is the culprit. Move it to ~/ as in Fix 1.
Fix 4: Enable Symlinks on NTFS Mounts (Last Resort)
Absolutely must work from /mnt/c/? You can try enabling NTFS symlink support, but it requires Developer Mode on Windows plus a WSL2 config tweak.
First, enable Developer Mode: Settings โ System โ For Developers โ Developer Mode โ On.
Then edit /etc/wsl.conf inside your WSL2 distro:
sudo nano /etc/wsl.conf
[automount]
options = "metadata"
The metadata option lets WSL2 store Linux file metadata โ including symlinks โ on the NTFS volume. Shut down WSL2 from PowerShell and restart:
# In PowerShell (admin)
wsl --shutdown
# Then reopen your WSL2 terminal
Test whether symlinks now work on the NTFS mount:
cd /mnt/c/Users/yourname/
ln -s test_target test_link
ls -la test_link
If ln -s succeeds, retry your Docker build. Still failing? Docker's layer extraction uses a different internal code path. Fix 1 or Fix 2 is more reliable.
Verification
Time to confirm the fix actually stuck. Remove the broken image first, then pull clean:
# Remove the partially pulled/broken image first
docker rmi python:3.11-slim 2>/dev/null || true
# Pull fresh
docker pull python:3.11-slim
No symlink error? You're through. Verify a full build while you're at it:
docker build --no-cache -t myapp:test .
docker run --rm myapp:test python3 --version
The --no-cache flag forces Docker to re-extract all layers โ exactly the operation that was failing before.
Prevention
- Keep your Docker projects in
~/โ not in/mnt/c/. Use your WSL2 home directory as the primary workspace when running Docker. You can still browse files from Windows Explorer via\\wsl$\Ubuntu\home\yourname\if needed. - Use VS Code with the WSL extension โ it transparently works with files inside WSL2's filesystem while you edit from Windows.
- Never set
data-rootto a Windows-mounted path โ always target a path inside/home/or/var/when overriding Docker's storage location.
The rule that covers everything: Docker on WSL2 works perfectly when everything stays on the Linux virtual disk. The moment image layers or build context touch an NTFS mount, symlinks break and you end up debugging this at 2 AM.

