Bind mount permissions - unexpected mounting as root:root

I have a directory /home/foo/test owned by foo:foo (uid=1000, gid=1000) on the host that I bind mount in the node Docker image as such:

$ docker run --rm --mount type=bind,source=/home/foo/test,target=/home/node node:14-bullseye ls -l /home/node/README.md
-rw-rw-r-- 1 node node 3196 Sep  7 15:13 /home/node/README.md

As you can see the mounted directory is owned by the same uid:gid as the host machine. This is what I expect.

The uid:gid of the node user in the container is also 1000:1000:

$ docker run --rm --user node node:14-bullseye id
uid=1000(node) gid=1000(node) groups=1000(node)

But when I run the exact same command on another computer, the mounted directory and it’s contents are owned by root:root:

$ docker run --rm --mount type=bind,source=/home/foo/test,target=/home/node node:14-bullseye ls -l /home/node/README.md
-rw-rw-r-- 1 root root 3196 Sep  7 15:13 /home/node/README.md

I thought Docker passed through file ownership when bind mounting in a container? Why does it work on one machine, and not the other? Is there any way to retain the ownership (i.e. have /home/node owned by 1000:1000 in the container)?

Both machines run Ubuntu Jammy with the same Docker versions:

Client: Docker Engine - Community
 Version:           20.10.18
 API version:       1.41
 Go version:        go1.18.6
 Git commit:        b40c2f6
 Built:             Thu Sep  8 23:11:43 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.18
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.6
  Git commit:       e42327a
  Built:            Thu Sep  8 23:09:30 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.8
  GitCommit:        9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

I wonder if it has something to do with rootless Docker as mentioned here:

But as far as I know I don’t run rootless Docker. I followed the instructions from here:

Is there an easy way to check if Docker is running in rootless mode?

You can run docker context ls to see if you are using the rootless context or just run docker info to get the current context name and docker data root which is different for rootless Docker.

1 Like

Thank you @rimelek for the quick reply. It looks like rootless mode might be the cause.

Outputs from machine without rootless (where the UIDs are as expected):

$ docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  compose: Docker Compose (Docker Inc., v2.10.2)

Server:
 Containers: 11
  Running: 0
  Paused: 0
  Stopped: 11
 Images: 297
 Server Version: 20.10.18
 Storage Driver: overlay2                                                                                              
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.15.0-48-generic
 Operating System: Ubuntu 22.04.1 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 15.5GiB
 Name: saibot
 ID: MB3C:JHK4:TRFH:H3RB:UBA5:N4HQ:LBBK:7JJY:57UO:4KYV:WWNF:GF7V
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
$ docker context ls
NAME        DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm

And the other machine that seems to run rootless:

$ docker info
Client:
 Context:    desktop-linux
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  compose: Docker Compose (Docker Inc., v2.10.2)
  extension: Manages Docker extensions (Docker Inc., v0.2.9)
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc., 0.6.0)
  scan: Docker Scan (Docker Inc., v0.19.0)

Server:
 Containers: 50
  Running: 37
  Paused: 0
  Stopped: 13
 Images: 28
 Server Version: 20.10.17
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.10.124-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.5GiB
 Name: docker-desktop
 ID: MM5K:IRVO:6JNJ:N3OZ:FLNA:3FU5:SVGP:W3LK:3MEZ:2D3C:IPEP:5OZZ
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5000
  127.0.0.0/8
 Live Restore Enabled: false
$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                                 KUBERNETES ENDPOINT                                 ORCHESTRATOR
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                     https://kubernetes.docker.internal:6443 (default)   swarm
desktop-linux *     moby                                                          unix:///home/foo/.docker/desktop/docker.sock

It is not rootless. It is Docker CE and Docker Desktop. On the second machine you installed Docker Desktop which runs a virtual machine and your containers will run inside that virtual machine. In that case you can’t just mount the host folder the same way into the containers, because you need to mount it first into the virtual machine. Although I tried Docker Desktop for Linux, I don’t remember how mounting works, because I usually use Docker Desktop for Mac or just Docker CE. On the second machine, if you have Docker CE installed too, you can switch back to the “default” context.

1 Like

It is not rootless. It is Docker CE and Docker Desktop. On the second machine you installed Docker Desktop which runs a virtual machine and your containers will run inside that virtual machine.

It will install a virtual machine even when installed on GNU/Linux? I didn’t know that.

We completely removed Docker from the second machine and installed just Docker Engine, and now mounts work as expected. Thanks for the help! :partying_face: