Troubleshooting “Too Many Levels of Symbolic Links” in Docker Host Volume Mounts with NFS


2 views

When mounting NFS volumes as host directories in Docker containers, you might encounter the frustrating "Too many levels of symbolic links" error. This typically happens when trying to access certain subdirectories within an automounted NFS volume.

Here's a typical scenario:

$ docker run -v /usr/groups/thing:/mnt/thing -ti imagename /bin/bash
# ls /mnt/thing/foo  # Works fine
# ls /mnt/thing/bar  # Fails with error
ls: cannot open directory /mnt/thing/bar: Too many levels of symbolic links

The issue stems from how automounted NFS volumes handle symbolic links and path resolution. When Docker bind-mounts the host directory, it doesn't properly handle the NFS automounter's symbolic link magic. The automounter creates symbolic links that point to the actual NFS mount point, and Docker's path resolution gets confused when following these links.

Solution 1: Use Direct NFS Mounts

Instead of relying on automount, mount the NFS share directly in your host's /etc/fstab:

nfs-server:/export/thing /usr/groups/thing nfs defaults 0 0

Then mount it manually before running Docker:

mount /usr/groups/thing
docker run -v /usr/groups/thing:/mnt/thing -ti imagename /bin/bash

Solution 2: Adjust Automount Configuration

Modify your automount configuration (/etc/auto.master and /etc/auto.groups) to use different mount options:

/usr/groups /etc/auto.groups --timeout=300 --ghost

In /etc/auto.groups:

thing -fstype=nfs,soft,intr nfs-server:/export/thing

Solution 3: Use Docker's Native NFS Support

For modern Docker versions, consider using direct NFS volume mounts:

docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=nfs-server,rw,soft,intr \
  --opt device=:/export/thing \
  nfs-volume

docker run --mount src=nfs-volume,target=/mnt/thing -ti imagename /bin/bash

If you can't modify the NFS setup, consider these workarounds:

1. Access files through the host's automount point first:

# On host
ls /usr/groups/thing/bar  # Trigger automount
# Then in container
ls /mnt/thing/bar

2. Use a different directory structure that doesn't trigger the automounter's link resolution:

mkdir -p /local/thing
mount --bind /usr/groups/thing /local/thing
docker run -v /local/thing:/mnt/thing -ti imagename /bin/bash

To better understand what's happening:

1. Check the actual mount points:

mount | grep thing
ls -l /usr/groups/thing

2. Examine the automounter's behavior:

automount -m

3. Trace the symbolic links:

namei -l /usr/groups/thing/bar

When mounting NFS volumes in Docker containers, you might encounter this puzzling scenario:

# Working directory
$ docker run -v /usr/groups/thing:/mnt -ti imagename ls /mnt/foo
file1 file2 file3

# Broken directory
$ docker run -v /usr/groups/thing:/mnt -ti imagename ls /mnt/bar
ls: cannot open directory /mnt/bar: Too many levels of symbolic links

This typically occurs when:

  • The host's NFS mount contains complex symlink structures
  • Docker's bind mount interacts poorly with NFS's automount features
  • The container's filesystem resolution differs from the host

Option 1: Use direct volume mounting

docker run -v /usr/groups/thing:/mnt:rshared -ti imagename

The rshared flag helps maintain proper mount propagation.

Option 2: Configure NFS client properly

# On the host machine
sudo echo "/usr/groups/thing *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
sudo exportfs -a

Option 3: Use Docker's NFS volume plugin

docker volume create \
    --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.1,rw \
    --opt device=:/usr/groups/thing \
    nfs-volume

docker run -v nfs-volume:/mnt -ti imagename

To diagnose symlink issues:

# On host machine
find /usr/groups/thing -type l -ls | awk '{print $11 " -> " $13}'

# In container
docker run -v /usr/groups/thing:/mnt -ti imagename \
    find /mnt -type l -exec ls -l {} \;

For time-sensitive applications, consider:

# Mount specific subdirectories instead of root
docker run -v /usr/groups/thing/bar:/bar -ti imagename

# Use rsync to copy files into a regular volume
docker run -v ./local_copy:/mnt -ti imagename \
    sh -c "rsync -avz nfs-server:/usr/groups/thing/bar /mnt/"