Naftuli Kay
Naftuli Kay

Reputation: 91640

Is there a way to remap a user id at runtime?

I have a container which has created a default user, which has UID 1000.

In my Dockerfile, I am creating the user:

RUN groupadd sudo && useradd -G sudo -u 1000 -U ${RUST_USER}

Now when I run the container, unless my current user has exactly UID 1000, volume permissions are messed up:

docker run -it --rm naftulikay/circleci-lambda-rust:latest \
    -v $PWD:/home/circleci/project \
    .local/bin/build

At runtime:

error: failed to write /home/circleci/project/Cargo.lock

Caused by:
  failed to open: /home/circleci/project/Cargo.lock

Caused by:
  Permission denied (os error 13)
Exited with code 101

This is because the user within the container has UID 1000 and the user outside the container has UID 1001.

I'd imagine that since this is already all virtual mappings into kernel namespaces, it would be possible to map internal UIDs to external UIDs from the container.

Is there a command line option which will allow me to dynamically remap UIDs as necessary?

Upvotes: 13

Views: 8200

Answers (2)

Jean-Roch B.
Jean-Roch B.

Reputation: 554

Like BMitch said you have many options depending on your system, but keep in mind you may have to restart your running process (php-fpm for example)

Some examples on how to achieve this: (you can run the commands outside the container with: docker container exec ...)

  • Example 1:

usermod -g 1007 www-data

It will update the uid of the user www-data to 1007

  • Example 2:

deluser www-data

adduser -u 1007 -D -S -G www-data www-data

It will delete the user www-data and recreate it with the uid 1007

  • Get pid and restart process

To restart a a running process, for example php-fpm, you can do it that way:

First get the pid, with one of the following command:

pidof php-fpm

ps -ef | grep -v grep | grep php-fpm | awk '{print $2}'

find /proc -mindepth 2 -maxdepth 2 -name exe -lname '*/php-fpm' -printf %h\\n 2>/dev/null | sed s+^/proc/++

Then restart the process with the pid(s) you got just before (if your process support USR2 signal):

kill -USR2 pid <-- replace pid by the number you got before

I found that the easiest way is to update the host or to build your container knowing the right pid (not always doable if you work with different environments)

Upvotes: 0

BMitch
BMitch

Reputation: 263726

The dynamic mapping of UID's between the container and host has been requested but I believe it requires kernel and filesystem changes to implement. Until then, you've got a few options:

  1. Make the host match the container. With host volumes, this isn't easy. But with named volumes, docker will initialize the volume to the contents of the image, including directory and file permissions, making it rather seamless. You would need to adjust your work flow to no longer have direct access to the data in the volume and instead use containers to access your data.

  2. Run the container as the host uid. You can mount /etc/passwd into the container as a host volume, and you can start the container as any uid (with docker run -u or the user entry in a compose file). The only downside is that files in the image may already be owned by the uid used to build the image, so they'll either need to be world readable (potentially writable) or moved to the volume.

  3. I've been known to start my container as root with an entrypoint that corrects the uid/gid mismatch based on the file permissions from a volume mount. Then the last step of my entrypoint is to drop permissions to that of the new uid and execute the container application. For an example of an entrypoint that does this, see this jenkins in docker example of mine that matches the jenkins gid to that of the docker socket mounted from the host.

Upvotes: 7

Related Questions