首页/云/Docker 容器速查/容器内使用非 root 用户运行
资源与安全50 条

容器内使用非 root 用户运行

镜像尽量以内置非 root 用户启动(USER 指令或 --user 指定):缩小应用被攻破后可触达的权限面,是容器安全的基础动作。

Docker 容器速查云更新于 2026-10-13

非 root 运行是什么

容器默认以 root 身份启动,容器里的 root 与宿主的 root 是同一个用户,只是被命名空间与权限机制圈定在容器视角内。一旦应用被攻破或者挂载了宿主目录,这份 root 权限的破坏力会被放大。把进程降级到非 root 用户运行,是容器安全成本最低、收益最直接的一项加固:镜像里用 USER 声明,或运行时用 --user 覆盖。

基本信息

镜像声明Dockerfile 里写 USER 10001:10001 或 USER app
运行时覆盖docker run --user 1000:1000 镜像(覆盖镜像声明)
检查方式docker image inspect -f '{{.Config.User}}' 镜像
常见内置用户node 镜像的 node、nginx 镜像的 nginx、python-slim 需自建
配套调整卷与绑定目录的属主要与容器内 UID 对齐
适用平台Linux 容器;Windows 容器用 ContainerUser 概念不同

典型使用场景

  • 对外暴露的 Web 服务:缩小被攻破后的影响面
  • 挂载了宿主目录的服务:避免在宿主上写出 root 属主文件
  • 多租户或共享集群:满足平台的安全基线要求
  • 配合只读根文件系统:让运行时无法写入镜像层
  • 审计整改项:扫描报告指出镜像以 root 运行时的直接修复动作
  • 共享数据卷的多个容器:统一 UID 避免互相写不进去

镜像内建用户与运行时降权

镜像内建用户与运行时降权
# 构建期创建固定 UID 的专用用户,并把工作目录授权给它
RUN groupadd -g 10001 app && useradd -u 10001 -g 10001 -m -s /sbin/nologin app
WORKDIR /srv/app
COPY --chown=10001:10001 ./app /srv/app
USER 10001:10001

# 复用基础镜像自带账号(node 镜像已提供 node 用户)
USER node

运行与验证

运行与验证
# 运行时覆盖镜像里的用户,快速验证降权后应用是否正常
 docker run -d --user 1000:1000 -v appdata:/data --name api app/api:1.4.2

# 确认容器内进程真实身份(应为非 0 的 uid)
 docker exec api id
 docker inspect -f '{{.Config.User}}' app/api:1.4.2

# 宿主侧检查:挂载目录里的新文件属主是否符合预期
 ls -ln ./data

降权后的常见表现

现象原因处理方向
启动即报权限拒绝目标目录属主仍是 root构建期 chown 或运行前调整宿主目录
写卷失败卷内既有内容属主不一致新建卷或统一 UID 后重建卷
监听 80 端口失败非 root 不能绑定低位端口改监听高位端口并由外部映射
无法读配置文件文件权限 600 且属主为 root改成 644 或授权给该用户
日志目录不可写目录未预先授权构建期创建并授权日志目录
端口是常见卡点:非 root 进程绑定 1024 以下端口需要额外能力授权。更稳妥的做法是应用监听 8080 之类的端口,由 docker run -p 80:8080 做映射。
只改启动用户而不调整目录权限,问题往往在运行一段时间后才暴露(首次写日志、首次落盘)。上线前应覆盖写入路径做一次完整回归。

易错点

  • 切换非 root 后写卷、写缓存目录失败是高频现象,目录属主必须在构建期或部署时一并授权
  • 只改启动用户不改目录权限,应用会在运行期才暴露问题,容易出现上线后才发现不可写的情况
  • 两个容器里都有名为 app 的用户但 UID 不同,共享卷时其中一个必然写不进去
  • 宿主上恰好存在同号普通用户时,容器写出的文件在宿主上显示为该用户名,别误判成挂载错人

数据来源与参考

  • Docker 官方文档:User 与安全实践(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌