Mounting QNAP NFS by filesystem path re-owned every file on another share
An NFS mount using the QNAP filesystem path instead of the export name resolved to a different share, and an image that runs chown -R at startup re-owned almost everything on it. How to mount correctly, how to verify by inode, and why to keep the chown output.
A container image started, ran its usual chown -R on the directory it
thought was its data, and quietly re-owned nearly every file of every other
application on the same NAS share. Nothing crashed. I found out because
something else stopped being able to read its own files.
The mount that lied
My Paperless volumes were defined as <nas>:/share/MD0_DATA/Paperless/....
On a QNAP with NFSv3 that is not an export path. The export is called
/Paperless, and the long form is the underlying filesystem path. The server
still answered, but it resolved the path to the root of a different share,
the one that held my Docker data. The Paperless image and the official
Postgres image both walk their mount at startup with find ... -exec chown,
so the walk re-owned that other share’s tree to the container user.
The real Paperless data was fine, because it had never been mounted. Every other app’s files on the share were not.
It was not consistent
Which directory the odd path resolved to changed with server state. First it
was another share’s root; later it was the right share’s root with the
sub-path ignored. That happened with and without nosharecache, through
Docker’s local NFS driver and through mount.nfs on the command line.
Treat a path that “works” this way as undefined rather than as slightly
wrong.
What to do instead
Mount by export name: <nas>:/<Share>. Ask the NAS which shares it exports
and use exactly those names. My fstab and Ansible mounts had the same long
form for other shares, so they carried the same risk and were on the fix
list.
Verify by inode, not by findmnt
/proc/mounts and findmnt print the device string you asked for, which
tells you nothing about what the server resolved it to. Compare
stat -c %i on a directory you know exists in the tree you meant. If the
inode is not the one you see when you look at the share on the NAS, you are
looking at something else.
Keep the evidence
The only record of what got re-owned is the container’s own --changes
output, and docker compose down deletes it together with the container.
If an image chowns its data at startup, run the first start with that
output going somewhere permanent.
Those two images are not unusual. Many images chown their volume on start, so a mount that points at the wrong tree is a much bigger event than a wrong path usually is.