Docker Containers with Unraid NFS: Fix Stale File Handle Errors
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…

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.
The Real Problem
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.
The Solution
Two simple components:
1. Make NFS Fail Fast
Update /etc/fstab to use soft mount options:
10.xx.xx.xx:/mnt/user/data /mnt/data nfs soft,intr,timeo=10,retrans=2,_netdev,x-systemd.automount,noatime 0 0⚠️ 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.
What this does:
soft– Operations fail quickly instead of hanging foreverintr– Allows interrupting stuck operationstimeo=10,retrans=2– Timeout after 1 second, retry twicex-systemd.automount– Auto-mount when accessed
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.
Remount it:
sudo systemctl daemon-reload
sudo umount /mnt/data
sudo systemctl restart mnt-data.mount2. Auto-Restart Containers When NFS Recovers
Create /home/youruser/docker/nfs-monitor.sh (adjust the path to match your setup):
#!/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
doneCreate /home/youruser/docker/nfs-monitor.service:
[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.targetInstall it:
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.serviceHow It Works
- 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
Watch It In Action
sudo journalctl -u nfs-monitor.service -fWhen Unraid reboots, you’ll see:
[Feb 09 13:24:15] NFS recovered - restarting media-stackWhat I Learned
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:
- Make NFS fail gracefully (soft mount)
- Detect when it recovers (simple health check)
- Restart containers (one docker compose command)
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.
Related Posts
Related
Build a Self-Healing AI Content Agent with Claude Agent SDK
I got tired of the content grind. Write a post, format it for X, reformat for Bluesky, render a video, upload to YouTube, cross-post to Instagram — repeat daily. It was eating 2-3 hours every day. So I built a self-healing AI content agent that does all of it. It runs 24/7 on a Mac…
Run a Claude Agent on a Schedule: Cron Jobs, Persistent Memory, and Error Recovery
Building an AI agent is the easy part. Making it run a Claude agent on a schedule reliably every day without babysitting — that’s where most tutorials stop. I run an autonomous Claude agent called Koda. It executes 15+ scheduled tasks daily: pulling analytics from YouTube, Google Search Console, and Instagram, scanning X for viral…
Automate Your Blog Publishing in 2026: From Draft to Live in One Command
Blog automation saved me 15-20 minutes per post. That’s the manual workflow: write in your editor, open WordPress, paste and reformat, upload a featured image, configure SEO metadata, hit publish. Multiply that by 3-4 posts per week and you’re losing hours to busywork that adds zero value. I built a system that takes a markdown…