-
Couldn't load subscription status.
- Fork 18.8k
Open
Labels
area/apiAPIAPIarea/kernelarea/volumesVolumesVolumesexp/expertkind/enhancementEnhancements are not bugs or new features but can improve usability or performance.Enhancements are not bugs or new features but can improve usability or performance.
Description
Use case: mount a volume from host to container for use by apache as www user.
The problem is currently all mounts are mounted as root inside the container.
For example, this command
docker run -v /tmp:/var/www ubuntu stat -c "%U %G" /var/www
will print "root root"
I need to mount it as user www inside the container.
pcallier, sengaya, arosequist, mhils, michaeljs1990 and 918 moreandrekosak, angelcervera, pahaz, felipemlemos, sergeyklay and 88 morefunkyfuture, andrewshvv, hadim, strarsis, benben and 83 moresvbrunov, bhack, MohammedNoureldin, Smart123s, zionyx and 9 morewilliam-plano-oxb, yngvark, jfloff, AlexMAS, pertu and 38 more
Metadata
Metadata
Assignees
Labels
area/apiAPIAPIarea/kernelarea/volumesVolumesVolumesexp/expertkind/enhancementEnhancements are not bugs or new features but can improve usability or performance.Enhancements are not bugs or new features but can improve usability or performance.
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
jpetazzo commentedon Oct 18, 2013
If you
chownthe volume (on the host side) before bind-mounting it, it will work.In that case, you could do:
(Assuming that
101:101is the UID:GID of thewww-datauser in your container.)Another possibility is to do the bind-mount, then
chowninside the container.crosbymichael commentedon Nov 28, 2013
@mingfang Will chown not work for you ?
bfirsh commentedon Jan 17, 2014
It would be useful to have a shortcut for this. I often find myself writing
runscripts that just set the permissions on a volume:https://github.com/orchardup/docker-redis/blob/07b65befbd69d9118e6c089e8616d48fe76232fd/run
aldanor commentedon Feb 18, 2014
What if you don't have the rights to
chownit?iwinux commentedon Jun 26, 2014
Would a helper script that
chownthe volume solve this problem? This scirpt can be theENTRYPOINTof your Dockerfile.SvenDowideit commentedon Jul 8, 2014
Can I say no - forcing users to add a helper script that does
(thanks @bfirsh for your eg)
is pretty terrible.
It means that the container has to be started as root, rather than running as the intended
redisuser. (as @aldanor alluded to )and it means a user can't do something like:
docker run -v /home/user/.app_cfg/ -u user application_container application:(SvenDowideit commentedon Jul 8, 2014
There is one way to make it work, but you need to prepare ahead of time inside your Dockrfile.
(I didn't test this example, I'm working on a chromium container that then displays on a separate X11 container that .... )
tianon commentedon Jul 10, 2014
And of course that method only works for direct new volumes, not bind
mounted or volumes-from volumes. ;)
thaJeztah commentedon Jul 14, 2014
Additionally, multiple containers using
volumes-fromwill have different uid/gid for the same user, which complicates stuff as well.frankamp commentedon Aug 7, 2014
@SvenDowideit @tianon that method doesn't work either. Full example:
Two runs, with and without a -v volume:
andrewmichaelsmith commentedon Nov 13, 2014
We're hitting an issue that would be solved by this (I think). We have an NFS share for our developer's home directories. Developers want to mount
/home/dev/git/projectin to Docker but cannot because we have Root Squash enabled.This forbids root from accessing
/home/dev/git/projectso when I try and run docker mounting/home/dev/git/projectI get anlstat permission deniederror.cpuguy83 commentedon Nov 13, 2014
@frankamp This is because docker's current preference is to not modify host things which are not within Docker's own control.
Your "VOLUME" definition is being overwritten by your
-vpwd`:/var/lib/reds`.But in your 2nd run, it is using a docker controlled volume, which is created in /var/lib/docker. When the container starts, docker is copying the data from the image into the volume, then chowning the volume with the uid:gid of the dir the volume was specified for.
I'm not sure there is much that can be done here, and unfortunately bind mounts do not support (as far as I can tell) mounting as a different uid/gid.
389 remaining items
snowdream commentedon Jan 21, 2025
I need ability to mount volume as user other than root too.
I need to run docker container as non-root user,but volumes are always mouted as root.
so, I have no permission to write to the volumes.
mfhepp commentedon Jan 21, 2025
Again, my analysis of the problem and a solution is described here:
Solution: mamba-org/micromamba-docker#407 (comment)
Full Analysis: mamba-org/micromamba-docker#407
It is in the context of
micromamba-dockerbut the underlying issue is generic and the solutions could be adjusted to other scenarios.polarathene commentedon Jan 21, 2025
Usually people who want to have a container with a non-root user are doing so as a "best practice" but I don't know if they give it much thought.
As @mfhepp points to, you might as well use Docker or Podman in rootless mode instead of rootful. Which will have the internal container user/groups mapped to something else on the host. There's some drawbacks to doing so, but that shouldn't be a surprise for those wanting non-root in a container.
Usually your concern is with someone compromising the container and being able to escape out of it to the host as the user running in the container. That requires capabilities that often aren't available by default to the containers root user. Using a non-root user will drop all capabilities and you'd then rely on granting a binary with any capabilities you'd need (via setcap) which can be insecure to do if those capabilities are the dangerous ones you are worried about a container root user having.
If the container user (root or non-root) has access to the Docker socket, and Docker is running rootful (default), then it doesn't matter if non-root when that socket can be used. If the socket isn't proxied and allows full control over the Docker daemon, the user can start a new container and become root through that, mount the host filesystem, etc. Now as the root user (even if that's only in a container for now, but access to the host filesystem where they can manipulate any file as root they can do the very thing you were trying to prevent.
I have seen projects create non-root users and advise users to mount the docker socket with the permissions for that non-root container user to leverage the socket. So please think carefully what you do with a non-root user, for the most part it's convenience to dropping all caps on the default root container user, or an attempt to prevent a user from making a container vulnerable because they grant additional caps / use
--privilegedin an attempt to solve something and the internet told them that'd do the trick.Do what @mfhepp suggested and push such users towards rootless containers (these still run as root within the container).
Otherwise you're often chasing after something in an effort to be secure but introduce new problems which tend to get workarounds that can make the container less secure (setcap when enforcing a capability that should otherwise be optional for example prevents someone who knows what their doing from securing their container properly).
Liken it to complicated password rules which leads users to make decisions that are less secure defeating the purpose entirely. A password for example can be very secure with just lowercase text, no numbers or special characters or other rules needed, just entropy. Depending on how the password is stored by a service
detailed snail summons slim lab coat(which provides 48 bits of entropy) is an example of what a secure password can look like, which on the surface goes against best practice advice users would be more familiar with seeing.Clockwork-Muse commentedon Jan 21, 2025
Docker rootless currently (or last I checked) causes problems because in contrast to Podman with its
--userns keep-id, there isn't a way to have the same uid on the host and in the container. This is a problem if you need any host access - often the case for mounting devices or displays, and completely breaks any devcontainers where the source is on the host and bind-mounted.devnoname120 commentedon Jan 22, 2025
@polarathene What if I want/need to mount the Docker socket inside a container without risking to pwn my entire system in case of a misconfiguration or an exploit in the socket proxy? Without being an expert about
CAP_stuffpolarathene commentedon Jan 22, 2025
Ah that's unfortunate. I've not used rootless much myself, but I did observe with Podman that I could have root in the container or any other container ID and a different one on the host and it'd be seamlessly mapped. This was with
--uidmapnot the other similar features.For example
--uidmap '+5000:@100:1'would map the container UID 5000 to the host UID 100 (IIRC with a bind-mount while the host ownership would be 100 on the host in the container it appears as 5000). This option uses@to get the relative/etc/subuidoffset in rootless which has an additional level of indirection (your host UID could be 1000 for example as the first host UID to map in/etc/subuid, so@1000maps to0), whereas rootful--uidmapcan directly map container ID or range to one on the host.I assume there is already a feature request for the equivalent in Docker, if not perhaps someone should raise that if they're not comfortable using Podman for that kind of requirement.
polarathene commentedon Jan 22, 2025
@devnoname120
TL;DR:
Rootless should not be mounting a rootful socket AFAIK, so it should be limited to the scope of rootless? I've only used rootless with Podman personally, so you might have to verify yourself. However if you use Docker Desktop on any platform this takes an alternative approach by isolating Docker into a VM, and IIRC official docs describe this as effectively rootless (escaping the container leaves you stuck in the VM), but for an improvement over that Docker Desktop offers ECI mode (Enhanced Container Isolation) as a more restrictive choice and not even the docker socket can be mounted without additional config to permit conditions for when that is allowed.
Thus for local usage, if you're using Docker Desktop that probably meets your security concerns when you configure that properly instead of hoping each image does something the way you want instead.
For production, you can leverage rootless if that brings more comfort, otherwise defer to whomever understands how to secure a server properly as Docker alone is not sufficient, and you should have a decent understanding of the images you trust and deploy. I understand many don't have the time or interest to learn that.
If you were implying that running a container as non-root user magically protects you from exploits with the socket you would be mistaken:
As you can see I can use the socket still.
dockerCLI uses the socket to interact with the Docker daemon too, so you can pull whatever image you like, volume mount what you like from the host system and run as whatever user in another container.Providing access to the socket just requires the ability to send a request through it, so if there's Python, JS or whatever else on the system that an attacker could exploit to run some script or command of their own they can perform that operation even if there's no shell or package manager on the container.
As for the socket proxy, I don't know what your question is for that. Using a proxy should be far safer than complete access to the socket, especially if you provide that to multiple containers of varying trust.
You instead have one container that you trust to access the socket and it locks down what can actually be used by the other containers proxying through it. Like anything a vulnerability could appear and be exploited yes, but you can minimize that by choosing an image for this functionality that is purely focused on this functionality, no redundant shell, package manager, or other commands, with a binary that is compiled rather than an interpreter like python or nodejs
I recently heard about https://github.com/wollomatic/socket-proxy (see their related locked down config example](https://github.com/wollomatic/socket-proxy#example-for-proxying-the-docker-socket-to-traefik)) which is probably a good example of that. I've not had time to give it a proper look yet, I have my own with a
Caddyfilewhich functions similarly.Using a unix socket as a listener you can share access via a volume to only the containers that should have the right to access the socket proxy, or you can use a private subnet. My approach supports multiple unix sockets for different access rights, something that is extra work for TCP listeners to support restricting client access correctly.
If you're just on the user end, you drop all caps like the linked project
compose.yamlshows. Should the image service actually require some caps to run (like it would if running as non-root), instead of the workaround the image maintainer would do to support non-root, they'd document the actual capabilities required to keep, which you as a user configure with--cap-add/cap_addshould you really care about the security aspect to the level.The non-root practice is mostly convenience in that sense so you don't have to think about this (but then you get issues like this one with volumes, or worse). The other worry it helps defend against tends to require you to do non-standard things you often shouldn't be doing.
If anyone wants to correct me on this I'd appreciate it, but AFAIK preferring a non-root user often pragmatically makes little real difference to security these days for the users it's intended to protect, if not actually reducing it when they run into caveats and resort to workarounds that reduce security.
dgutson commentedon Jan 22, 2025
Happily moved to podman, unsubscribing from this issue. I recommend others to do likewise.
dwt commentedon Jan 22, 2025
Just came here to say the same thing: Docker is ok to use on personal machines, but for deployments on servers Podman is far superior.
With Podman I can bind mount my files into the container and specify exactly as what UID I want them to be mounted. This completely solves all permission problems.
And of course you also get rid of the daemon running as root that all container users need to talk to. Happy Days.
devnoname120 commentedon Jan 22, 2025
@dgutson Will do too
@polarathene Thank you for your detailed explanations, I'm not sure how to say this politely but I'm not a noob and I think you misunderstood my use case. Hopefully it will help others though
oerp-odoo commentedon Jan 22, 2025
@polarathene there is also a case to run as non root, not just for security. Its very annoying, when mounted data becomes owned by root, when you initiate container from some other user. For example all data is mounted from
user1home directory, but some data still becomes owned by root, which causes access errors.Clockwork-Muse commentedon Jan 22, 2025
There are at least some applications where, the last time I checked, the uids actually had to match internally/externally, because of how it tried to open them or something. This was mostly around x11 sockets, and I haven't touched it in a while... So it didn't matter if you mapped the uid this way, because the application went "I need to do this thing with the current uid, and pass that in a request", which of course didn't exist on the host (or represented a completely wrong one or similar).
jdmarshall commentedon Apr 9, 2025
@dgutson i don’t think podman has a solution for this for created volumes, do they?