Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker user in and out of container: what is the correspondence (UID/GID), seeing effects I don't understand

Tags:

docker

I am trying to understand the functioning of docker well enough to come to reasonable confidence I am using it securely. One advice for this is to always use a USER statement in a Dockerfile. In trying to understand the effect of this I run into some trouble.

Concrete questions:

  1. What mechanism allows the host kernel to deal with users that only exist in the container?
  2. Why does run2 below show the directory belongs to testuser but doesn't allow the ls when in the directory?
  3. Why does run3 below show the directory belong to testuser?

Version information at the bottom of this question.

Setup

I have the following Dockerfile

FROM alpine@sha256:1354db23ff5478120c980eca1611a51c9f2b88b61f24283ee8200bf9a54f2e5c

LABEL version 2.0
LABEL description "Test image for setting user"

RUN adduser -D testuser1   ## sometimes removed
RUN adduser -D testuser2   ## sometimes removed
RUN adduser -D testuser

USER testuser

CMD sh

I build this with

docker build -t kasterma/testuser:1 .

Then run with

docker run -ti -v /home/kasterma/test-user/:/test-home kasterma/testuser:1

The directory /home/kasterma/test-user/ is the directory that contains the Dockerfile.

Run 1: remove both lines marked ##sometimes removed in the Dockerfile.

[root@datalocal01 test-user]# docker run -ti -v /home/kasterma/test-user/:/test-home kasterma/testuser:1
/ $ ls -lh
...
drwx------    2 1001     1001          40 Dec 30 14:08 test-home
...

Here is shows user and group both as being 1001; which is the user and groupid of kasterma in the host. In this context testuser has uid and gid 1000.

Also

/ $ cd test-home
sh: cd: can't cd to test-home

Run 2: remove only the second line marked ##sometimes removed in the Dockerfile.

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:12 test-home
...

and

/ $ cd test-home
/test-home $ ls
ls: can't open '.': Permission denied

Now testuser and kasterma have the same uid and gid (though the one has them in the container, and the other on the host). Why can I cd, but not ls?

Run 3: remove neither line marked ##sometimes removed in the Dockerfile.

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:15 test-home
...

and

/ $ cd test-home
sh: cd: can't cd to test-home

Now testuser has uid and gid 1002, so not the same as kasterma. But the listing shows it as testuser, but the cd command fails.

Version information

the OS version (running on a VM in VirtualBox)

[root@datalocal01 test-user]# uname -a
Linux datalocal01 3.10.0-514.2.2.el7.x86_64 #1 SMP Tue Dec 6 23:06:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

and for docker

[root@datalocal01 test-user]# docker version
Client:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-59.el7.centos.x86_64
 Go version:      go1.6.3
 Git commit:      3999ccb-unsupported
 Built:           Thu Dec 15 17:24:43 2016
 OS/Arch:         linux/amd64

Server:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-59.el7.centos.x86_64
 Go version:      go1.6.3
 Git commit:      3999ccb-unsupported
 Built:           Thu Dec 15 17:24:43 2016
 OS/Arch:         linux/amd64
like image 777
kasterma Avatar asked Dec 30 '16 14:12

kasterma


1 Answers

When the host is running SELinux it's possible you can't access the file system content if it isn't labeled. From man docker-run

Labeling systems like SELinux require that proper labels are placed on volume content mounted into a container. Without a label, the security system might prevent the processes running inside the container from using the content. By default, Docker does not change the labels set by the OS. To change a label in the container context, you can add either of two suffixes :z or :Z to the volume mount. These suffixes tell Docker to relabel file objects on the shared volumes. The z option tells Docker that two containers share the volume content. As a result, Docker labels the content with a shared content label. Shared volume labels allow all containers to read/write content. The Z option tells Docker to label the content with a private unshared label. Only the current container can use a private volume.

So, instead of disabling SELinux you could try

docker run -ti -v /home/kasterma/test-user/:/test-home:Z kasterma/testuser:1

See Using Volumes with Docker can Cause Problems with SELinux for more details.

I tried your use cases on my box (without SELinux and having Docker version 1.12.5): I always get the right "testuser" ownership and I'm able to change directory and list its content (my local uid is 1000 and I haven't more users above it). So, may be your problem is due to the older Docker version.

If not related to SELinux neither old Docker version, the behavior you described seems related to User Namespaces.

Check if your host's kernel enables User Namespace (CentOS 7, that seems the distro you are using, doesn't enable it by default.

Look at Using User Namespaces on Docker that describes how to enable User namespaces on CentOS 7 and how to check the correct behavior.

About User Namespace details, look at several sites like:

Introduction to User Namespaces in Docker Engine

Docker Security

User namespaces have arrived in Docker!

Docker for your users - Introducing user namespace

You can find a clear description about permissions in Docker volumes before introduction of User Namespaces (before Docker 1.10) at Deni Bertovic blog - Handling Permissions with Docker Volumes.

Hope it helps.

like image 199
gile Avatar answered Sep 22 '22 22:09

gile