Creating a file on a mounted volume in Docker as the external user (and not as root)

Gabor Szabo - Apr 26 '23 - - Dev Community

For a long time I had this problem that I did not know how to solve:

When you run Docker on a linux host, mount an external folder, all the files created in the docker will be owned by user root on the host file-system.

Finally I think I understood how this works and found a solution. At least a partial solution.

The Problem

Here is the problem again:

I run docker and mount the current folder as /opt inside the container:

$ docker run -it --rm -w /opt -v$(pwd):/opt ubuntu:23.04 bash
Enter fullscreen mode Exit fullscreen mode

When inside the container I create a file and then exit the container:

# touch hello
# exit
Enter fullscreen mode Exit fullscreen mode

If I look at the ownership of the file on my host computer (which is also Ubuntu):

$ ls -l hello
Enter fullscreen mode Exit fullscreen mode

I get:

-rw-r--r-- 1 root root 0 Apr 26 20:35 hello
Enter fullscreen mode Exit fullscreen mode

The file is now owned by user root.

Solution

Add the --user ubuntu parameter to the command:

$ docker run -it --rm -w /opt -v$(pwd):/opt --user ubuntu ubuntu:23.04 bash
Enter fullscreen mode Exit fullscreen mode

Inside the container create a file and exit:

$ touch world
$ exit
Enter fullscreen mode Exit fullscreen mode

Outside, on the host, check the ownership:

$ ls -l world
-rw-r--r-- 1 gabor gabor 0 Apr 26 20:38 world
Enter fullscreen mode Exit fullscreen mode

It is now owned by gabor which is my regular user.

Explanation

In Linux each user has a user id. The user root has the id 0 on every Linux machine and I guess also on macOS, but I have not checked it.
So both on my host computer and inside the Docker container the user root has the same id.

When I ran docker in the first example (without passing the --user parameter), inside the container I became user root.
Any file I created then got the userID 0 as its owner. This is also the user root outside, so that's why the file is owned by
root on the host system.

The first real user on Ubuntu (and I think in general on every Linux and Unix system) will get the id 1000. So the user ID of my
user "gabor" on my host computer has the ID 1000. I could verify this by running the id command on my computer.

The Docker image 23.04 also comes with a default real user account which is called ubuntu and it also has the ID 1000.
When in the 2nd example I used the --user ubuntu flag I entered the container as user ubuntu. If I ran the id command there
I'd see:

$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev)
Enter fullscreen mode Exit fullscreen mode

showing that this user in the container also has the ID 1000.

I found out about this by listing all the users using the cat /etc/passwd command. It is the last row.

So when I created a file on the mounted volume the file was created as user ubuntu (id 1000) inside the container.
However on my host machine that id belongs to my regular user, so my computer sees that file as own by user gabor (id 1000).

Just as if I created it as my regular user on the host computer.

This solves the problem.

Notes and warnings

If on the host system your ID is not 1000, then this will not work, but you can create a user in the container with the ID you have
and use that username.

Now that inside the container I am user ubuntu I don't have the privileges of user root so I cannot make changes
to any of the system files. In particular I cannot install any extra software using apt.

I have not tried any other images. I am quite sure that the default user in a CentOS-based image won't be called "ubuntu", if it has one.

CentOS

After a little pause I though I'll try CentOS as well.

I ran

$ docker run -it --rm -w /opt -v$(pwd):/opt  centos:7 bash
Enter fullscreen mode Exit fullscreen mode

and then inside the container

# cat /etc/passwd
Enter fullscreen mode Exit fullscreen mode

This showed that all the user IDs are below 1000, they are all system-related users. So I need to create a user.

I created a Dockerfile with the following content:

FROM centos:7
RUN useradd centos
Enter fullscreen mode Exit fullscreen mode

That RUN command will create a user with the username centos:

Built my own images:

$ docker build -t mycentos .
Enter fullscreen mode Exit fullscreen mode

Ran docker using that images:

$ docker run -it --rm -w /opt -v$(pwd):/opt --user centos mycentos bash
Enter fullscreen mode Exit fullscreen mode

Inside the containe I first checked the id then created a file, then exited:

$ id
$ cat /etc/passwd
$ exit
Enter fullscreen mode Exit fullscreen mode

Outside I checked:

$ ls -l cent
-rw-rw-r-- 1 gabor gabor 0 Apr 26 22:26 cent
Enter fullscreen mode Exit fullscreen mode

It looks fine.

Conclusion

On Ubuntu there is already a user called ubuntu, on CentOS there is no user, but we can create one easily.
I assume on any other image you would either already had a user or you could create one.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .