Docker Compose NFS Bind Mount: Fix .env Conflicts & Permissions
Recently while setting up a Docker Compose-based media stack, I ran into a tricky issue. It looked like everything was working, the containers were up, the mounts were in place, and the files were visible, yet I couldn’t write to my NFS share from inside the containers. Here’s what happened, and how I fixed it….

Recently while setting up a Docker Compose-based media stack, I ran into a tricky issue. It looked like everything was working, the containers were up, the mounts were in place, and the files were visible, yet I couldn’t write to my NFS share from inside the containers.
Here’s what happened, and how I fixed it.
What I Was Building
I had a shared NFS mount point at /mnt/data on my Ubuntu Docker host, and I wanted to use environment variables to keep things clean:
In my .env:
# Data Share
DATA=/mnt/dataAnd in my docker-compose.yml:
volumes:
- ${DATA}:/dataThis approach seemed solid — clean, reusable, and friendly for future automation.
What Looked Right
- The container started successfully
- The NFS share mounted properly on the host
- Inside the container, I could
ls /dataand see all my files and folders - Permissions looked fine on the host: the NFS export mapped to UID/GID 1000, which matched the container user
Where It Broke
Despite being able to browse files, I couldn’t write to the mounted folder inside the container.
Commands like:
touch /data/testfilewould fail with:
Permission deniedWhat I Discovered
After hours of chasing NFS export settings, UID mapping, and file ownership, I tried one small change that fixed it instantly:
volumes:
- /mnt/data:/dataJust like that, everything worked — I could read, write, and delete files inside /data from within the container.
The Real Issue
While using environment variables like ${DATA} in volume paths is supported by Docker Compose, they don’t always behave reliably with bind mounts, especially when the host path involves mounted filesystems like NFS.
Even though ${DATA} correctly pointed to /mnt/data
- Docker Compose resolved the variable
- Mounted the NFS share correctly
- But bind permissions didn’t behave as expected when the path came via an environment variable
It’s unclear whether there was a problem with Docker Compose, the NFS client, or how the filesystem is resolved. But using an env variable in the volume path led to silent permission issues, even though everything else appeared fine.
What I Recommend
Use an absolute path for bind mounts
volumes:
- /mnt/data:/dataIt’s simple, reliable, and eliminates variable resolution from the bind mount path.
Final Thoughts
If your container can read but not write to an NFS-mounted volume using an environment variable, try an absolute path instead. It might just save you hours of debugging.
Found this helpful? I share more hands-on fixes and Docker tips from my homelab over on GitHub and here on the blog.
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…