The problem I encountered with the solution to create a file on a mounted volume in Docker as the external user (and not as root) was that using a regular user internally made it impossible to execute commands as root. In particular it made it impossible to install packages using the package-management system of the operating system.

This is not a problem during regular software development because you rarely need to install extra system-packages. Most (all?) programming languages have a tool to install their own packages as regular user. However, there are cases, especially when you first try to create a Docker image to run a particular piece of software, that you will need to install several system-level packages and also run the code of the project that might create files in the current working directory which is mapped to the external disk.

I found two solution for this. Both involves switching between regular user and root user but they work in different ways.

The first solution does not need any extra installation, but you probably need more self-discipline and in a way I feel it is more error-prone.

The second needs us to install sudo.

Without sudo

In this version we return to launching Docker and being user root inside.

$ docker run -it -w /opt -v$(pwd):/opt --name ubu ubuntu:23.04 bash

Now we are user root. At this time we can install extra packages. e.g. installing less:

# apt-get update
# apt-get install -y less

The we can switch to the regular ubuntu user and work as regular user inside Docker (e.g. create a file in the folder that was mapped to the external disk):

# su - ubuntu
$ cd /opt
$ touch hello

If we would like to install another system-wide package, we need to use exit to leave the ubuntu user, then we can install more packages and can get back to our regular user again with su - ubuntu. (The - tells Linux to set up the full environment of that user.)

In order to leave the Docker container we need to execute exit twice. First to exit the regular user to become root and then to exit the container.

With sudo

For this solution we need a little-bit of setup. We have the following Dockerfile:

examples/docker-sudu/Dockerfile

FROM ubuntu:23.04
RUN apt-get update && \
    apt-get install -y sudo && \
    usermod -aG sudo ubuntu && \
    echo "ubuntu  ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

  • We install sudo.
  • Add the user ubuntu to the group that can use sudo.
  • We add ubuntu to the sudoers file and allow it to execute commands without providing a password.

We build the image:

docker build -t myubuntu .

Then run it as the user ubuntu

docker run -it -w /opt -v$(pwd):/opt --name ubu --user ubuntu myubuntu bash

Now we use it as the regular user ubuntu.

$ touch file_in_mounted_folder

If we would like to install as system-wide package we can use sudo:

$ sudo apt-get update
$ sudo apt-get install -y less

When we would like to exit we need to type exit only once.