How to have consistent ownership of mounted volumes in docker?

Viewed 153

I'm trying to understand some weird behavior that I'm seeing on docker. I want to run a container which writes cached data to a mounted volume from the host which I can later reuse for future executions of the container and that can also be read from the host.

On the host, I see that my user has the user id 1000:

# This is on the host
$ id
uid=1000(juan-munoz) gid=1000(juan-munoz) groups=1000(juan-munoz)...

I'm running the container without any special flags for the user so it runs as root:

# This is on the container
$ id
uid=0(root) gid=0(root) groups=0(root)

Also, there is already a user with id=1000:

# The image is provided by AWS and apparently it includes a user with this ID
$ id -nu 1000
ec2-user

I have mounted a directory with -v /some/local/directory:/var/mounted. Locally, this directory is owned by my user (id=1000):

# On the host
ls -ld /some/local/directory
drwx------ 2 juan-munoz juan-munoz 4.0K Jun 21 16:21 /some/local/directory

In the container, if I go check the directory I see that it's currently owned by root. This is the first part that I don't understand.

# ls -ld /var/mounted
drwx------ 2 root root 4096 Jun 22 03:36 /var/mounted

Why root? I would have expected that with the mount the user id would be respected.

If I then try to change the user to 1000, this happens:

# Inside the container
$ chown -R 1000:1000 /var/mounted
ls -ld /var/mounted
drwx------ 2 ec2-user 1000 4096 Jun 22 03:36 /var/mounted

Which looks good to me, but when I do that, if I look at what happened on the host I see the following:

# On the host
ls -ld /some/local/directory
drwx------ 2     100999     100999 4.0K Jun 21 20:36 /some/local/directory

So either the host or the container has a messed up owner. If I chown 1000:1000 on the host, the container sees it as root, if I chown 1000:1000 on the container, the host sees it as 100999.

What am I doing wrong here?

Repro steps

$ mkdir $HOME/testing
$ docker run -it --name=ubuntu-test --entrypoint="/bin/bash" --rm -v $HOME/testing:$HOME/testing ubuntu:latest

# Inside the container
$ cd /home/myusername/testing
$ touch file.txt
root@b98b7a5445e3:/home/juan-munoz/testing# ls -l
total 0
-rw-r--r-- 1 root root 0 Jun 30 23:52 file.txt

# Outside the container
$ ls -l $HOME/testing
total 0
-rw-r--r-- 1 juan-munoz juan-munoz 0 Jun 30 16:52 file.txt

Observed behavior:

  • In some computers, from outside the container, the file is owned by the local user. In others, it's owned by root.

Expected behavior:

  • To be consistent across computers
1 Answers

I encountered the same issue under Ubuntu 22.04 with Docker Desktop installed. After the Docker Desktop is uninstalled and the Docker Engine is reinstalled, things just go the way I want them to: having consistent ownership of mounted directories between the host and the container.

Here is my use case: I want to start an Ubuntu 20.04 container and use it as the compiling environment for my application. The Dockerfile is:

FROM ubuntu:20.04
ARG USER=docker
ARG UID=1000
ARG GID=1000

# create a new user with same UID & PID but no password
RUN groupadd --gid ${GID} ${USER} && \
    useradd --create-home ${USER} --uid=${UID} --gid=${GID} --groups root && \
    passwd --delete ${USER}
# add user to the sudo group and set sudo group to no passoword
RUN apt update && \
    apt install -y sudo && \
    adduser ${USER} sudo && \
    echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# prevent tzdata to ask for configuration
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt -y install tzdata
RUN apt install -y build-essential git cmake

# setup default user when enter the container
USER ${UID}:${GID}
WORKDIR /home/${USER}

The building script:

#!/bin/bash
set -e
UID=$(id -u)
GID=$(id -g)
docker build --build-arg USER="$USER" \
    --build-arg UID="$UID" \
    --build-arg GID="$GID" \
    --tag "ubuntu-env" \
    --file ./Dockerfile \
    --progress=plain \
    .

Since I use it as the compiling environment, the whole home directory is mounted for convenience:

#!/bin/bash
set -e
docker run -it \
    --name "build-env" \
    --user "${USER}" \
    --workdir "${PWD}" \
    --env TERM=xterm-256color \
    --volume="$HOME":"$HOME" \
    --detach \
    "ubuntu-env" \
    /bin/bash

Somehow, with the Docker Desktop installed, the owner of the mounted home directory is always the root rather than the host user. After it is uninstalled, the mounted directory now gets the expected owner in the container, aka the host user.

Related