构建以非root用户运行的Ubuntu容器遇权限问题求助
Ubuntu 24.04容器挂载主机目录权限问题解决
问题背景
要构建Ubuntu 24.04镜像用于代码构建,要求以非root用户(builder)运行容器,主机与容器共享源码目录,但容器内写入目录时出现权限拒绝。对比Ubuntu 20.04镜像无此问题,同时使用-u $(id -u)运行容器时,会出现无用户名、用户不在sudo组的异常。
涉及的Dockerfile
FROM ubuntu:24.04 USER root RUN apt-get update -y RUN apt-get install sudo useradd adduser -y RUN useradd -ms /bin/bash builder | chpasswd RUN adduser builder sudo RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers USER jenkins RUN mkdir -p /home/builder/workspace WORKDIR /home/builder/workspace
权限问题现象
容器内builder用户uid为1001,主机用户uid为1000,挂载主机目录后无法写入:
builder@95cfd88194e0:~/workspace$ touch x touch: cannot touch 'x': Permission denied
使用-u $(id -u)运行时的异常:
I have no name!@0123456789ab:/my/path$ id uid=1005 gid=0(root) groups=0(root)
问题原因
- Linux权限本质:文件系统权限基于uid/gid而非用户名,主机与容器uid不匹配时,容器用户无对应目录的读写权限。
- Ubuntu 20.04 vs 24.04差异:Ubuntu 24.04基础镜像对用户权限、文件系统权限的默认配置更严格,没有兼容uid不匹配的场景;而20.04镜像或当时的Docker版本可能对挂载目录权限有宽松处理,掩盖了uid不匹配的问题。
解决方案
方案一:启动容器时动态创建匹配主机uid/gid的用户(推荐)
无需修改主机配置,也不用固定容器内的uid,灵活适配不同主机环境。
步骤1:调整Dockerfile
FROM ubuntu:24.04 USER root # 安装必要工具,gosu用于安全切换用户 RUN apt-get update -y && apt-get install -y sudo gosu && rm -rf /var/lib/apt/lists/* # 创建工作目录 RUN mkdir -p /home/builder/workspace WORKDIR /home/builder/workspace # 添加启动脚本 COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] CMD ["bash"]
步骤2:编写entrypoint.sh脚本
#!/bin/bash set -e # 从环境变量获取主机的uid/gid,默认值设为1000(常见普通用户uid) HOST_UID=${HOST_UID:-1000} HOST_GID=${HOST_GID:-1000} # 创建匹配主机gid的用户组 if ! getent group "${HOST_GID}" > /dev/null; then groupadd -g "${HOST_GID}" builder-group fi # 创建匹配主机uid的用户,并加入sudo组 if ! getent passwd "${HOST_UID}" > /dev/null; then useradd -m -u "${HOST_UID}" -g "${HOST_GID}" -s /bin/bash builder usermod -aG sudo builder echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers fi # 切换到builder用户执行容器命令 exec gosu builder "$@"
步骤3:构建并运行容器
# 构建镜像 docker build --tag build . # 运行容器,传入主机当前用户的uid和gid docker run -it \ -v /home/myname/workspace:/home/builder/workspace \ -e HOST_UID=$(id -u) \ -e HOST_GID=$(id -g) \ build
方案二:临时调整主机目录权限(不推荐,安全性低)
直接给主机共享目录添加其他用户的写入权限:
chmod o+w /home/myname/workspace
此方法简单但会降低目录安全性,仅适合测试场景。
方案三:挂载主机用户信息文件
通过挂载主机的/etc/passwd和/etc/group,让容器直接使用主机的用户命名空间:
docker run -it \ -v /home/myname/workspace:/home/builder/workspace \ -u $(id -u):$(id -g) \ -v /etc/passwd:/etc/passwd:ro \ -v /etc/group:/etc/group:ro \ build
此方法无需修改镜像,但需确保主机用户信息在容器中有效,若需要sudo权限,需额外配置容器内的sudo规则。
内容的提问来源于stack exchange,提问作者Uri London
相关产品推荐
相关产品推荐

