boxboat/fixuid

Correct owner not set on mounted volumes if the runtime UID is the same as the container UID

jrd opened this issue · 2 comments

jrd commented

If you defined a docker container user, which result in UID 1000 for instance,
and you run the container also with the UID 1000.

The fixuid binary will say that UID matches and that it didn’t need to do anything (

fixuid/fixuid.go

Lines 141 to 142 in 543e124

if existingUser == containerUser {
logInfo("runtime UID '" + runtimeUID + "' already matches container user '" + containerUser + "' UID")
)

Let’s say now that I also mounted a named volume to this container on /my-volume and configured fixuid to fix that path in its config file.
Docker-compose will create the volume, sets the owership to root and mount the volume to /my-volume.

As the Go variable needChown will stay with the false value, the code near

fixuid/fixuid.go

Lines 187 to 199 in 543e124

if needChown {
// proccess /proc/mounts
mounts, err := parseProcMounts()
if err != nil {
logger.Fatalln(err)
}
// store the current mountpoint
var mountpoint string
// this function is called for every file visited
visit := func(filePath string, fileInfo os.FileInfo, err error) error {
will not be executed and the /my-volume will not be owned by user 1000 but by user root 0.

How can this be circumvent?

You need to pre-stage directories and set the correct ownership in the Dockerfile for directories that will become docker volumes. For example, this will not work, because /my-volume is not pre-staged so it is created with UID/GID 0:0 at runtime

FROM node:alpine

RUN apk add --no-cache curl

RUN USER=node && \
    GROUP=node && \
    curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
    chown root:root /usr/local/bin/fixuid && \
    chmod 4755 /usr/local/bin/fixuid && \
    mkdir -p /etc/fixuid && \
    printf "user: $USER\ngroup: $GROUP\npaths:\n- /\n- /my-volume" > /etc/fixuid/config.yml

USER node:node
ENTRYPOINT ["fixuid"]
CMD ["sh", "-c", "touch /my-volume/test && ls -lh /my-volume"]
WORKDIR /my-volume

When run:

$ docker build -t test .
$ docker run --rm -u 1001:1001 -v /my-volume test
fixuid: fixuid should only ever be used on development systems. DO NOT USE IN PRODUCTION
fixuid: updating user 'node' to UID '1001'
fixuid: updating group 'node' to GID '1001'
fixuid: recursively searching path /
fixuid: chown /home/node
fixuid: recursively searching path /my-volume
touch: /my-volume/test: Permission denied

The solution is to pre-stage /my-volume with the correct permissions in your Dockerfile:

# add this before USER node:node

RUN mkdir /my-volume && \
    chown node:node /my-volume

Now everything works:

$ docker build -t test .
$ docker run --rm -u 1001:1001 -v /my-volume test
fixuid: fixuid should only ever be used on development systems. DO NOT USE IN PRODUCTION
fixuid: updating user 'node' to UID '1001'
fixuid: updating group 'node' to GID '1001'
fixuid: recursively searching path /
fixuid: chown /home/node
fixuid: skipping mounted path /my-volume
fixuid: recursively searching path /my-volume
fixuid: chown /my-volume
total 0      
-rw-r--r--    1 node     node           0 Nov  6 14:46 test
jrd commented

Great!
Thanks for the quick and complete answer. I close :-)