GitHub Actions中如何非root权限运行Docker容器?
权限错误的核心逻辑是Docker挂载卷的权限校验基于UID/GID数值匹配,和用户名、组名无关。
你在Dockerfile中创建的dev用户默认UID/GID固定为1000,但GitHub Workflows宿主机的runner用户默认UID为1001,挂载进容器的工作目录属主为宿主机UID 1001的用户,容器内UID 1000的dev用户自然没有写入权限。直接传入-u $USER参数时,Docker会在容器内查找名为runner的用户,镜像中未创建该用户就会抛出用户不存在的错误。
以下方案均不需要全程使用root用户执行业务脚本,符合最小权限安全要求:
方案1:构建镜像时动态传入匹配的UID/GID(最优方案)
GitHub Actions运行环境可通过id -u、id -g获取当前runner用户的实际UID、GID,构建镜像时将这两个值作为构建参数传入,让容器内dev用户的UID/GID和宿主机runner完全一致,挂载后权限天然匹配,不需要额外调整。
原有Dockerfile无需修改,直接调整Workflow中的构建、运行命令即可:# 构建镜像时传入UID/GID参数 docker build -t project --build-arg USER_UID=$(id -u) --build-arg USER_GID=$(id -g) . # 正常用dev用户运行容器即可 docker run -u dev -v $PWD:/home/dev/project project /bin/bash -c "./my_script.sh"方案2:启动时临时修正权限(适合无需重建镜像的场景)
如果不想重新构建镜像,可以启动时先用root用户仅执行一次目录权限修正,再切换到dev用户执行业务脚本,业务逻辑全程运行在非root权限下:docker run -v $PWD:/home/dev/project project /bin/bash -c "chown -R dev:dev /home/dev/project && su dev -c './my_script.sh'"方案3:运行时直接指定UID数值(适合轻量脚本场景)
Docker支持直接传入UID/GID数值指定运行用户,不需要容器内存在对应的用户名,可直接传入宿主机runner的ID运行:docker run -u $(id -u):$(id -g) -v $PWD:/home/dev/project -w /home/dev/project project /bin/bash -c "./my_script.sh"该方案的缺陷是容器内无对应命名用户,部分依赖用户名读取配置的脚本可能运行异常。
- 不要为了快速解决问题直接给挂载目录设置777权限,会引入额外安全风险
- 不要全程使用root用户执行业务脚本,一旦出现容器逃逸风险,攻击者可直接获取宿主机高权限
- 不要硬编码UID/GID为1000,不同CI环境、不同本地用户的UID可能存在差异,动态获取ID的方案通用性更强
内容的提问来源于stack exchange,提问作者Poperton

