Tools: Docker Containers with Unraid NFS: Fix Stale File Handle Errors - 2025 Update

Tools: Docker Containers with Unraid NFS: Fix Stale File Handle Errors - 2025 Update

The Real Problem

The Solution

1. Make NFS Fail Fast

2. Auto-Restart Containers When NFS Recovers

How It Works

Watch It In Action

What I Learned

Related Posts If you’re running Docker containers with Unraid NFS shares, or any server serving NFS shares, you’ve probably encountered the “stale file handle” problem. I’m running Proxmox as my hypervisor with multiple VMs: one running Unraid as my NAS, and another running my media stack (Plex, Radarr, Sonarr, etc.) in Docker containers. The Docker VM pulls media from Unraid via NFS. Everything worked fine—until Unraid rebooted or the network hiccuped. The containers would keep running, but they’d lose access to the media files. Plex would say “media unavailable,” and I’d have to manually restart every container. After trying way too many solutions (including building a whole systemd monitoring stack I later deleted), I finally figured out the simple fix. When Docker containers mount an NFS share and the NFS server goes away, they get stuck with “stale file handles.” Even when the mount comes back, the running containers can’t recover—they need to be restarted. The default NFS mount behavior makes things worse: operations hang indefinitely, freezing everything that touches the mount. This approach is aimed at read‑mostly media workloads (Plex, Radarr, Sonarr, etc.) where brief downtime and container restarts are acceptable. If you store databases, application state, or other write‑critical data on NFS, you should not blindly copy these mount options—see the warnings below. Two simple components: Update /etc/fstab to use soft mount options: ⚠️ Important: soft NFS mounts are convenient for media workloads but risky for write‑heavy or critical data. On timeouts, they can cause failed or partial writes that applications may not handle safely. For anything that writes important data (databases, appdata, downloads), prefer hard mounts with appropriate timeouts and consider different strategies (local storage, SMB, or separate mounts) instead. This fixes the freezing. Now when Unraid is down, operations just fail instead of locking up your terminal. Note: On many modern Linux distributions, intr is largely ignored; the main behaviour change here comes from soft and the timeout/retry options. Create /home/youruser/docker/nfs-monitor.sh (adjust the path to match your setup): Create /home/youruser/docker/nfs-monitor.service: When Unraid reboots, you’ll see: I initially built a complex solution with multiple systemd units, path watchers, and startup scripts. It was overkill and didn’t even solve the stale file handle problem. Also, this is not a one‑size‑fits‑all NFS best practice. For Unraid shares that host critical write‑heavy workloads, you may want different NFS options, or even SMB/local storage instead, and handle recovery without soft mounts. The real fix was simple: Works with any Docker containers that depend on NFS mounts. Adjust the paths to match your setup. If you’re working on similar infrastructure or automation challenges, you can find more of this at Build & Automate. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

10.xx.xx.xx:/mnt/user/data /mnt/data nfs soft,intr,timeo=10,retrans=2,_netdev,x-systemd.automount,noatime 0 0 10.xx.xx.xx:/mnt/user/data /mnt/data nfs soft,intr,timeo=10,retrans=2,_netdev,x-systemd.automount,noatime 0 0 10.xx.xx.xx:/mnt/user/data /mnt/data nfs soft,intr,timeo=10,retrans=2,_netdev,x-systemd.automount,noatime 0 0 sudo systemctl daemon-reload sudo umount /mnt/data sudo systemctl restart mnt-data.mount sudo systemctl daemon-reload sudo umount /mnt/data sudo systemctl restart mnt-data.mount sudo systemctl daemon-reload sudo umount /mnt/data sudo systemctl restart mnt-data.mount #!/bin/bash # Monitor NFS health and restart containers when it recovers CHECK_INTERVAL=30 STATE_FILE="/tmp/nfs-state" while true; do # Test if NFS is actually working (not just mounted) if timeout 2 ls /mnt/data/media >/dev/null 2>&1; then new_state="ok" else new_state="bad" fi old_state=$(cat "$STATE_FILE" 2>/dev/null || echo "unknown") echo "$new_state" > "$STATE_FILE" # If it just recovered, restart containers if [ "$old_state" = "bad" ] && [ "$new_state" = "ok" ]; then echo "[$(date)] NFS recovered - restarting media-stack" cd /home/youruser/docker/media-stack && docker compose restart fi sleep $CHECK_INTERVAL done #!/bin/bash # Monitor NFS health and restart containers when it recovers CHECK_INTERVAL=30 STATE_FILE="/tmp/nfs-state" while true; do # Test if NFS is actually working (not just mounted) if timeout 2 ls /mnt/data/media >/dev/null 2>&1; then new_state="ok" else new_state="bad" fi old_state=$(cat "$STATE_FILE" 2>/dev/null || echo "unknown") echo "$new_state" > "$STATE_FILE" # If it just recovered, restart containers if [ "$old_state" = "bad" ] && [ "$new_state" = "ok" ]; then echo "[$(date)] NFS recovered - restarting media-stack" cd /home/youruser/docker/media-stack && docker compose restart fi sleep $CHECK_INTERVAL done #!/bin/bash # Monitor NFS health and restart containers when it recovers CHECK_INTERVAL=30 STATE_FILE="/tmp/nfs-state" while true; do # Test if NFS is actually working (not just mounted) if timeout 2 ls /mnt/data/media >/dev/null 2>&1; then new_state="ok" else new_state="bad" fi old_state=$(cat "$STATE_FILE" 2>/dev/null || echo "unknown") echo "$new_state" > "$STATE_FILE" # If it just recovered, restart containers if [ "$old_state" = "bad" ] && [ "$new_state" = "ok" ]; then echo "[$(date)] NFS recovered - restarting media-stack" cd /home/youruser/docker/media-stack && docker compose restart fi sleep $CHECK_INTERVAL done [Unit] Description=NFS Mount Health Monitor After=docker.service [Service] Type=simple User=youruser Group=youruser ExecStart=/home/youruser/docker/nfs-monitor.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target [Unit] Description=NFS Mount Health Monitor After=docker.service [Service] Type=simple User=youruser Group=youruser ExecStart=/home/youruser/docker/nfs-monitor.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target [Unit] Description=NFS Mount Health Monitor After=docker.service [Service] Type=simple User=youruser Group=youruser ExecStart=/home/youruser/docker/nfs-monitor.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target chmod +x /home/youruser/docker/nfs-monitor.sh sudo cp /home/youruser/docker/nfs-monitor.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now nfs-monitor.service chmod +x /home/youruser/docker/nfs-monitor.sh sudo cp /home/youruser/docker/nfs-monitor.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now nfs-monitor.service chmod +x /home/youruser/docker/nfs-monitor.sh sudo cp /home/youruser/docker/nfs-monitor.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now nfs-monitor.service sudo journalctl -u nfs-monitor.service -f sudo journalctl -u nfs-monitor.service -f sudo journalctl -u nfs-monitor.service -f [Feb 09 13:24:15] NFS recovered - restarting media-stack [Feb 09 13:24:15] NFS recovered - restarting media-stack [Feb 09 13:24:15] NFS recovered - restarting media-stack - soft – Operations fail quickly instead of hanging forever - intr – Allows interrupting stuck operations - timeo=10,retrans=2 – Timeout after 1 second, retry twice - x-systemd.automount – Auto-mount when accessed - When Unraid reboots, the NFS share becomes inaccessible - The monitor detects it’s down (state = “bad”) - When Unraid comes back, the mount auto-reconnects - The monitor detects it’s working again (state = “ok”) - It automatically restarts the media-stack containers - Containers get fresh file handles and everything works - Make NFS fail gracefully (soft mount) - Detect when it recovers (simple health check) - Restart containers (one docker compose command) - Why Docker Compose and .env Can Break NFS Bind Mounts - Provision Ubuntu VMs with NoCloud on Proxmox - Automate Proxmox VMs with Cloud-Init