github编辑

USER 指定当前用户

基本语法

USER <用户名>[:<用户组>]
USER <UID>[:<GID>]

USER 指令切换后续指令(RUN、CMD、ENTRYPOINT)的执行用户。


为什么要使用 USER

笔者强调:以非 root 用户运行容器是最重要的安全实践之一。

root 用户运行的风险:
┌────────────────────────────────────────────────────────┐
│  容器内 root  ←─ 可能逃逸 ─→  宿主机 root             │
│      │                            │                    │
│      └── 漏洞利用 ───────────────→ 完全控制宿主机     │
└────────────────────────────────────────────────────────┘

非 root 用户运行:
┌────────────────────────────────────────────────────────┐
│  容器内普通用户  ──逃逸后──→  宿主机普通用户          │
│      │                            │                    │
│      └── 权限受限,危害降低 ─────→ 无法控制系统       │
└────────────────────────────────────────────────────────┘

基本用法

创建并切换用户

使用 UID/GID


用户必须已存在

USER 指令只能切换到已存在的用户:

创建用户的方式

Debian/Ubuntu

Alpine

选项
说明

-r (useradd) / -S (adduser)

创建系统用户

-g

指定主组

-G

指定附加组

-u

指定 UID

-s /bin/false

禁用登录 shell


运行时切换用户

使用 gosu(推荐)

在 ENTRYPOINT 脚本中切换用户时,不要使用 susudo,应使用 gosuarrow-up-right

docker-entrypoint.sh

为什么不用 su/sudo

问题
su/sudo
gosu

TTY 要求

需要

不需要

信号传递

不正确

正确

子进程

exec 替换

容器中使用


运行时覆盖用户

使用 -u--user 参数:


文件权限处理

切换用户后,确保应用有权访问文件:


最佳实践

1. 始终使用非 root 用户

2. 使用固定 UID/GID

便于在宿主机和容器间共享文件:

3. 多阶段构建中的 USER


常见问题

Q: 权限被拒绝

解决:确保目录权限正确

Q: 无法绑定低于 1024 的端口

非 root 用户无法绑定 80、443 等端口。

解决

  1. 使用高端口(如 8080)

  2. 在运行时映射端口:docker run -p 80:8080


本章小结

要点
说明

作用

切换后续指令的执行用户

语法

USER usernameUSER UID:GID

前提

用户必须已存在

运行时覆盖

docker run -u

切换工具

使用 gosu,不用 su/sudo

延伸阅读

最后更新于