Docker and –userns-remap, how to manage volume permissions to share data between host and container?

In docker, files created inside containers tend to have unpredictable ownership while inspecting them from the host. The owner of the files on a volume is root (uid 0) by default, but as soon as non-root user accounts are involved in the container and writing to the file system, owners become more or less random from the host perspective.

It is a problem when you need to access volume data from the host using the same user account which is calling the docker commands.

  • Error response from daemon: Cannot start container
  • Mount (link) a single file from a docker container volume
  • is docker0 a bridge(l2) or a router(or a l3 bridge)?
  • Get composer (php dependency manager) to run on a docker image build
  • curl Flask web service inside Docker container
  • How to restrict access to path in Docker container?
  • Typical workarounds are

    • forcing users uIDs at creation time in Dockerfiles (non portable)
    • passing the UID of the host user to the docker run command as an environment variable and then running some chown commands on the volumes in an entrypoint script.

    Both these solutions can give some control over the actual permissions outside the container.

    I expected user namespaces to be the final solution to this problem. I have run some tests with the recently released version 1.10 and –userns-remap set to my desktop account. However, I am not sure that it can make file ownership on mounted volumes easier to deal with, I am afraid that it could actually be the opposite.

    Suppose I start this basic container

    docker run -ti -v /data debian:jessie /bin/bash
    echo 'hello' > /data/test.txt
    exit
    

    And then inspect the content from the host :

    ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/
    
    -rw-r--r-- 1 100000 100000 6 Feb  8 19:43 test.txt
    

    This number ‘100000’ is a sub-UID of my host user, but since it does not correspond to my user’s UID, I still can’t edit test.txt without privileges. This sub-user does not seem to have any affinity with my actual regular user outside of docker. It’s not mapped back.

    The workarounds mentioned earlier in this post which consisted of aligning UIDs between the host and the container do not work anymore due to the UID->sub-UID mapping that occurs in the namespace.

    Then, is there a way to run docker with user namespace enabled (for improved security), while still making it possible for the host user running docker to own the files generated on volumes?

  • Error running rails app on docker container of official Ruby image
  • Cassandra Nodes not linking in Docker
  • Docker Wordpress High CPU Usage
  • Why are Docker build commands running so slow in Elastic Beanstalk?
  • Docker image > google/cadvisor:latest
  • Increasing mysql max_connections to 1024 in a docker container
  • One Solution collect form web for “Docker and –userns-remap, how to manage volume permissions to share data between host and container?”

    If you can prearrange users and groups in advance, then it’s possible to assign UIDs and GIDs in such specific way so that host users correspond to namespaced users inside containers.

    Here’s an example (Ubuntu 14.04, Docker 1.10):

    1. Create some users with fixed numeric IDs:

      useradd -u 5000 ns1
      
      groupadd -g 500000 ns1-root
      groupadd -g 501000 ns1-user1
      
      useradd -u 500000 -g ns1-root ns1-root
      useradd -u 501000 -g ns1-user1 ns1-user1 -m
      
    2. Manually edit auto-generated subordinate ID ranges in /etc/subuid and /etc/subgid files:

      ns1:500000:65536
      

      (note there are no records for ns1-root and ns1-user1 due to MAX_UID and MAX_GID limits in /etc/login.defs)

    3. Enable user namespaces in /etc/default/docker:

      DOCKER_OPTS="--userns-remap=ns1"
      

      Restart daemon service docker restart, ensure /var/lib/docker/500000.500000 directory is created.

      Now, inside containers you have root and user1, and on the host — ns1-root and ns1-user1, with matching IDs

      UPDATE: to guarantee that non-root users have fixed IDs in containers (e.g. user1 1000:1000), create them explicitly during image build.

    Test-drive:

    1. Prepare a volume directory

      mkdir /vol1
      chown ns1-root:ns1-root /vol1
      
    2. Try it from a container

      docker run --rm -ti -v /vol1:/vol1 busybox sh
      echo "Hello from container" > /vol1/file
      exit
      
    3. Try from the host

      passwd ns1-root
      login ns1-root
      cat /vol1/file
      echo "can write" >> /vol1/file
      

    Not portable and looks like a hack, but works.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.