Both put data outside the container. They fail differently, and on a hosting server the difference matters more than usual.
Named volumes
Docker manages the storage. Portable, easy to back up as a unit, and the container's own user owns the contents, so permissions generally just work. The downside is that browsing the data means going through Docker rather than opening a directory.
Bind mounts
A host path mapped in. You can edit files with your normal tools, back them up with your normal backups, and see exactly where they are. This is the right choice for website content that a human edits.
The UID problem, which is the actual subject of this post
Containers see numbers, not names. If the process inside runs as UID 33 (www-data on Debian) and your host files are owned by UID 1001, the container gets permission denied on files that look perfectly fine to you.
Match the numbers. Three ways, in order of preference:
The anonymous volume trap
If an image declares
A Type of "volume" with a 64-character hex name is anonymous. Name it before you put anything in it you care about.
Named volumes
Code:
docker run -v appdata:/var/lib/app myimage
Docker manages the storage. Portable, easy to back up as a unit, and the container's own user owns the contents, so permissions generally just work. The downside is that browsing the data means going through Docker rather than opening a directory.
Bind mounts
Code:
docker run -v /home/user/site:/var/www/html myimage
A host path mapped in. You can edit files with your normal tools, back them up with your normal backups, and see exactly where they are. This is the right choice for website content that a human edits.
The UID problem, which is the actual subject of this post
Containers see numbers, not names. If the process inside runs as UID 33 (www-data on Debian) and your host files are owned by UID 1001, the container gets permission denied on files that look perfectly fine to you.
Code:
# what the container runs as
docker exec mycontainer id
# what the host thinks
ls -n /home/user/site | head
Match the numbers. Three ways, in order of preference:
- Run the container as the host owner:
--user 1001:1001. Cleanest, works with most images. - Change host ownership to match the container's UID. Fine for data that only the container touches, bad for files a human also edits over SFTP.
- Some images accept
PUIDandPGIDenvironment variables and adjust internally. Convenient where offered, not a standard.
The anonymous volume trap
If an image declares
VOLUME /data and you do not map anything there, Docker creates an anonymous volume. It survives restarts and disappears on a recreate — so the data lasts exactly long enough for you to trust it. Check with:
Code:
docker inspect mycontainer --format '{{range .Mounts}}{{.Type}} {{.Name}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'
A Type of "volume" with a 64-character hex name is anonymous. Name it before you put anything in it you care about.