podmanbind9

Podman volume mount permissions issues


I'm on a Fedora computer, working with the official ISC Bind9 container image (which appears to be based on Debian Linux), and I'm having trouble with permissions.

I start the container as follows:

podman run --name bind9 \
 -p 11153:53/udp \
 -p 11153:53/tcp \
 -v /home/devops/work/dns/primary/etc:/etc/bind/:rw,Z,U \
 -v /home/devops/work/dns/primary/cache:/var/cache/bind:rw,Z,U \
 -v /home/devops/work/dns/primary/lib:/var/lib/bind:rw,Z,U \
 -v /home/devops/work/dns/primary/log:/var/log:rw,Z,U \
 internetsystemsconsortium/bind9:9.20 -4 -g -c /etc/bind/named.conf

There are no podman logs to reference, so I set the -g flag on named so that errors go to stderr. I get the following error messages that appear to be access issues between my host and the container???

09-Nov-2024 21:26:44.329 the working directory is not writable
09-Nov-2024 21:26:44.330 loading configuration: permission denied
09-Nov-2024 21:26:44.330 exiting (due to fatal error)

Digging into the container layers, I see that in the container a bind user is used to run named in the ENTRYPOINT part of the container.

...
23 VOLUME [/etc/bind /var/cache/bind /var/lib/bind /var/log] 0 B
24 EXPOSE map[443/tcp:{} 53/tcp:{} 53/udp:{} 853/tcp:{} 0 B
25 ENTRYPOINT ["/usr/sbin/named" "-u" "bind"] 0 B
26 CMD ["-f" "-c" "/etc/bind/named.conf" "-L" 0 B
...

I know I can override the CMD and I did so above in podman command, but is it possible to override ENTRYPOINT so that it's not the bind user but the root user? I wonder if that might help.

Furthermore, is there anything I can do to deal with having a user account in the container that is not on the container host machine? I'm guessing that this is more of a podman thing and it would just work with Docker...but for podman do I really have to create a bind user with the same UID:GID on the host machine as in the container just to get it to work??

Note: I'm running this as a rootless container by the devops user on my Fedora machine and all of the mounted volumes are in the user's home directory tree.

EDIT:

I made a bit of progress with troubleshooting. If indeed it is a UID perms type problem...I did uncover the UID of the bind user in the container:

podman run -d --name=bind9 -p 11153:53/udp -p 11153:53/tcp internetsystemsconsortium/bind9:9.20
podman exec -it bind9 /bin/sh
/ # cat /etc/passwd...
bind:x:100:101:Linux User,,,:/var/cache/bind:/sbin/nologin

EDIT:

I tried adding --userns=keep-id:uid=100,gid=101 to the podman run command but I still get the same exact issue. I'm not sure what to try next.


Solution

  • All the issues you are running into are well-known in running containers rootless. Fundamentally, it's because running rootless was only an afterthought when Docker was designed, so the entire ecosystem of container images expect root privileges. Podman therefore has to work around this using user namespaces.

    I will refer you to these two excellent RedHat articles explaining the tricks behind rootless containers and the troubles you can run into:


    Do read these two articles, but the TLDR is that you are seeing nobody on your host because the UID 100 in the user namespace (and hence the container) gets mapped to some other UID (likely 500,000+; check your /etc/subuid) on the host, which does not have permissions in your home directory.

    do I really have to create a bind user with the same UID:GID on the host machine as in the container just to get it to work??

    Don't do this. Never do this. This reduces your portability to basically zero, not to mention it exposes implementation details of the container to the host, which could easily cause conflicts.

    All this is part of the reason why using volume mounts is recommended for almost all persistent storage needs of rootless containers. You only set up permissions correctly within the namespace, and let Podman handle all the UID and GID mapping. This article shows how you can do that, but it may not be necessary:


    In practice, I would recommend creating two volumes: one to mount on /etc/bind/, and the other on /var/. So your run command would look something like this, after you've create these volumes using podman volume create:

    ...
    -v bind-etc:/etc/bind/:rw,Z \
    -v bind-var:/var/:rw,Z \
    ...
    

    Ideally I would use one volume and mount its two different subpaths as /etc/bind/ and /var/ in the container, but that is not yet supported in Podman. But it seems like there is a PR submitted just earlier today which is very nice to see. Depending on when you are reading this answer and what version of Podman you have installed, you may wish to do this instead.