14

I'm having a slightly annoying issue while using a Docker container (I'm on Ubuntu, so no virtualization like VMWare or b2d). I've built my image, and have a running container that has one shared (mounted) directory from my host, and one shared (mounted) file from my host. Here's the docker run command in full:

docker run -dit \
-p 80:80 \
--name my-container \
-v $(pwd)/components:/var/www/components \
-v $(pwd)/index.php:/var/www/index.php \
my-image

This works great, and both /components (and its contents) and the file are shared appropriately. However, when I want to make changes to either the directory (e.g. adding a new file or folder), or edit the mounted file (or any file in the directory), I'm unable to do so due to incorrect permissions. Running ls- lFh shows that the owner and group for the mounted items have been changed to libuuid:libuuid. Modifying either the file or parent directory requires root permissions, which impedes my workflow (as I'm working from Sublime Text, not Terminal, I'm presented with a popup for admin privs).

Why does this occur? How can I work around this / handle this properly? From Managing Data Volumes: Mount a Host File as a Data Volume:

Note: Many tools used to edit files including vi and sed --in-place may result in an inode change. Since Docker v1.1.0, this will produce an error such as “sed: cannot rename ./sedKdJ9Dy: Device or resource busy”. In the case where you want to edit the mounted file, it is often easiest to instead mount the parent directory.

This would seem to suggest that instead of mounting /components and /index.php, I should instead mount the parent directory of both. Sounds great in theory, but based on the behavior of the -v option and how it interacts with /directory, it would seem that every file in my parent directory would be altered to be owned by libuuid:libuuid. Additionally, I have lots of things inside the parent directory that are not needed in the container - things like build tools, various files, some compressed folders, etc. Mounting the whole parent directory would seem to be wasteful.

Running chown user:group on /components and /index.php on my host machine allow me to work around this and seem to continue to sync with the container. Is this something I'll need to do every time I run a container with mounted host volumes? I'm guessing that there is a more efficient way to do this, and I'm just not finding an explanation for my particular use-case anywhere.

I am using this container for development of a module for another program, and have no desire to manage a data-only container - the only files that matter are from my host; persistence isn't needed elsewhere (like a database, etc).

  • Dockerfile
  • /setup
  • Created on pastebin to avoid an even longer post. Never expires.

After creating the image, this is the run command I'm using:

docker run -dit \
    -p 80:80 \
    --name my-container \
    -v $(pwd)/components:/var/www/wp-content/plugins/my-plugin-directory/components \
    -v $(pwd)/index.php:/var/www/wp-content/plugins/my-plugin-directory/index.php \
    my-image
  • Why not create a directory and add this two files as symbolic link inside that directory to that so that you can mount the created directory to the container. – Viswesn Aug 03 '15 at 06:02
  • @Viswesn, can you expand on why you think that would be an appropriate solution? –  Aug 03 '15 at 06:39
  • Sounds like you've got something fishy running in your CMD script that is doing the rogue chowning (it's not expected behaviour for docker to chown existing or files mounted inside the containers) - can you post that, and your Dockerfile? – Chris McKinnel Aug 03 '15 at 16:12
  • @ChrisMcKinnel I've added the Dockerfile, the CMD script (`/setup`), and the run command I'm using (actual directory/file names altered for obscurity, of course). –  Aug 04 '15 at 06:10
  • Can you `cat /etc/passwd` on your host and find the `uid` of `libuuid`, then `docker exec -ti [container] bash` and then `cat /etc/passwd` and find the corresponding `uid` in your container? I have a feeling it'll be `nginx` as you do multiple `chown -R nginx:nginx /var/www` - maybe you're chowning everything you mount to `nginx` on every container start. – Chris McKinnel Aug 04 '15 at 08:30
  • By the way, check out http://stackoverflow.com/questions/26500270/understanding-user-file-ownership-in-docker-how-to-avoid-changing-permissions-o/26514736#26514736 for an explanation on how file permissions work with docker and why chowning mounted files in your containers can have unwanted affects on your host. – Chris McKinnel Aug 04 '15 at 08:32
  • @ChrisMcKinnel That pointed me in the right direction - the `uid`s of my host machine's `libuuid` user and the container's `nginx` user matched. I had a read over that answer, and it provided a clear understanding of file ownership permissions. To resolve my issue, I've excluded the mounted directory and file from the `chown -R nginx:nginx /var/www/wp-content/*` command my `setup` script. Thanks! Would you mind making an answer summarizing this information so you can reap the sweet, sweet e-karma? –  Aug 05 '15 at 05:34
  • Good stuff, you're welcome. – Chris McKinnel Aug 05 '15 at 09:36
  • Related: https://stackoverflow.com/questions/23544282/what-is-the-best-way-to-manage-permissions-for-docker-shared-volumes – Ciro Santilli OurBigBook.com Nov 11 '18 at 12:51

1 Answers1

4

It looks like your chown -R nginx:nginx ... commands inside your container are changing the ownership bits on your files to be owned by libuuid on your host machine.

See Understanding user file ownership in docker: how to avoid changing permissions of linked volumes for a basic explanation on how file ownership bits work between your host and your docker containers.

Community
  • 1
  • 1
Chris McKinnel
  • 14,694
  • 6
  • 64
  • 67