使用Podman实现容器与宿主机用户映射的安全方案问询
我正在学习容器相关知识,现在要配置一个需要持久化存储、且能对宿主机某目录拥有rwx权限的rootful容器,挂载方式为:
--volume=/host/example:/container/example
容器内的服务以用户foo(UID=1000)运行。我清楚如果不做UID/GID映射,不能直接给宿主机目录设0777权限,这太不安全;如果把宿主机目录权限设为1000:1000,只有宿主机默认用户能访问,而且我没法修改容器内foo的UID,否则会破坏服务依赖的权限。
尝试过的方案
- 单独映射容器foo用户到宿主机foo用户
我在宿主机创建了UID:GID为989:989的用户foo,然后用以下参数映射:
--uidmap=1000:989 --gidmap=1000:989
但这个方案无效,因为容器需要调用NVIDIA驱动,必须映射root用户,否则nvidia-container-toolkit会报错:
conmon[3523966]: conmon <nwarn>: runtime stderr: error executing hook `/nix/store/cnkyyycyfiws224mkhf42hrm6kyvggxw-container-toolkit-container-toolkit-1.15.0-rc.3/bin/nvidia-ctk` (exit code: 1) {"msg":"error executing hook `/nix/store/cnkyyycyfiws224mkhf42hrm6kyvggxw-container-toolkit-container-toolkit-1.15.0-rc.3/bin/nvidia-ctk` (exit code: 1)","level":"error","time":"2024-11-26T23:04:03.632243Z"}
不确定是不是NixOS的bug。
- 映射容器root到宿主机root+映射foo用户
这个方案是唯一可行的,但安全性极差:
--uidmap=0:0 --gidmap=0:0 --uidmap=1000:989 --gidmap=1000:989
如果容器被攻陷,容器root直接拥有宿主机root权限,完全失去沙箱隔离意义。
我的NixOS配置
comfyui = { image = "docker.io/obeliks/comfyui:latest-cu121"; autoStart = true; labels = { "io.containers.autoupdate" = "registry"; }; ports = [ "8188:8188" ]; environment = { HF_HOME = "/cache/huggingface/hub"; COMFYUI_PATH = "/app"; COMFYUI_MODEL_PATH = "/app/models"; COMFYUI_EXTRA_ARGS = "--lowvram"; }; volumes = [ "/export/ai/images:/app/output" #权限问题 ... ]; extraOptions = [ "--name=comfyui" "--gpus=all" #"--uidmap=0:0" #"--gidmap=0:0" #"--uidmap=1000:989" #"--gidmap=1000:989" ]; };
最优安全方案推荐
方案1:用户命名空间完整映射(推荐)
nvidia-container-toolkit仅需要容器内root能访问NVIDIA设备文件,不需要映射到宿主机root。可以给容器root分配宿主机上的非root UID范围,同时单独映射foo用户到宿主机989:989:
--uidmap=0:100000:65536 --gidmap=0:100000:65536 --uidmap=1000:989:1 --gidmap=1000:989:1
- 解释:
0:100000:65536把容器内UID 0-65535映射到宿主机UID 100000-165535,容器root对应宿主机100000(非root);1000:989:1单独覆盖容器内UID1000(foo)到宿主机UID989的映射。 - 配套操作:将宿主机
/export/ai/images目录所有者设为989:989,权限设为0700或0750:
sudo chown 989:989 /export/ai/images sudo chmod 0700 /export/ai/images
- NixOS配置修改:把
extraOptions替换为:
extraOptions = [ "--name=comfyui" "--gpus=all" "--uidmap=0:100000:65536" "--gidmap=0:100000:65536" "--uidmap=1000:989:1" "--gidmap=1000:989:1" ];
方案2:Podman --userns=keep-id 简化映射(如果用Podman)
如果使用Podman,可直接用--userns=keep-id参数自动处理用户映射,指定将容器内foo用户映射到宿主机989用户:
--userns=keep-id:uid=989,gid=989 --gpus=all
这个方案无需手动编写uidmap,Podman会自动维护用户命名空间,同时兼容NVIDIA驱动(需确保nvidia-container-toolkit支持用户命名空间)。
方案3:临时调整NVIDIA设备权限(不推荐)
如果上述方案无法生效,可临时调整宿主机NVIDIA设备文件权限,让宿主机989用户能访问:
sudo chown :989 /dev/nvidia* sudo chmod g+rw /dev/nvidia*
然后仅映射foo用户:
--uidmap=1000:989:1 --gidmap=1000:989:1
但此方案每次宿主机重启后都需要重新设置设备权限,可靠性较差。
内容的提问来源于stack exchange,提问作者sigg

