github编辑

7.11 USER 指定当前用户

7.11.1 基本语法

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

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


7.11.2 为什么要使用 USER

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

spinner

7.11.3 基本用法

创建并切换用户

FROM node:20-alpine

## 1. 创建用户和组

RUN addgroup -g 1001 appgroup && \
    adduser -u 1001 -G appgroup -D appuser

## 2. 设置目录权限

WORKDIR /app
COPY --chown=appuser:appgroup . .

## 3. 切换用户

USER appuser

## 4. 后续命令以 appuser 身份运行

CMD ["node", "server.js"]

使用 UID/GID


7.11.4 用户必须已存在

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

创建用户的方式

Debian/Ubuntu

Alpine

选项
说明

-r (useradd) / -S (adduser)

创建系统用户

-g

指定主组

-G

指定附加组

-u

指定 UID

-s /bin/false

禁用登录 shell


7.11.5 运行时切换用户

使用 gosu (推荐)

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

docker-entrypoint.sh

为什么不用 su/sudo

问题
su/sudo
gosu

TTY 要求

需要

不需要

信号传递

不正确

正确

子进程

exec 替换

容器中使用


7.11.6 运行时覆盖用户

使用 -u--user 参数:


7.11.7 文件权限处理

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


7.11.8 最佳实践

1. 始终使用非 root 用户

2. 使用固定 UID/GID

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

3. 多阶段构建中的 USER


7.11.9 常见问题

Q:权限被拒绝

解决:确保目录权限正确

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

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

解决

  1. 使用高端口 (如 8080)

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


最后更新于