可以且可选地在
Dockerfile
中指定用户。 Docker 镜像是通过构建 Dockerfile
. 创建的
如果指定了用户名,则在从 Docker 映像创建的 Docker 容器内运行的进程将以指定用户身份运行。
当 Docker 容器运行时,该用户名是否必须作为主机操作系统上的用户存在?
如果容器运行并且用户在主机系统上不存在会发生什么?
在
Dockerfile
中,可以使用指定用户名
user: <username>
用户不需要“存在”,无论是在主机上还是在容器中。
作为一个基本示例,假设您的主机 shell 是一个“丰富”的 shell,例如 bash 或 zsh,您可以尝试运行
docker run -u "$RANDOM" busybox id
这将选择一个随机数字用户 ID 并作为该 ID 运行主容器进程。 这里的主要过程是 id(1),它只是打印出当前有效的用户和组 ID 及其名称(如果已知)。 如果您运行它足够多次,它有一个很小的机会会选择容器中恰好存在的用户 ID
/etc/passwd
,但大多数情况下它将是任意随机用户。
容器不以 root 身份运行通常是最佳实践,但除了用户 ID 不为 0 之外,uid 实际是什么通常并不重要。 因此,我经常看到的一件事是设置容器,使其各种文件可供世界读取,然后在 Dockerfile 末尾切换到一些非 root
USER
。 通常图像会运行 adduser(8) 来创建用户,但这并不是真正必要的。
FROM some-standard-language-image
# Run the entire build sequence as root
USER root
RUN apt-get install ...
WORKDIR /app
COPY language-specific-dependencies.yml ./
RUN install-language-specific-dependencies
COPY ./ ./
RUN language-specific-build
# Only now switch to non-root
USER 12345 # the specific uid doesn't matter
CMD ["my-application"]
即使主机或容器的
/etc/passwd
文件中未列出用户 12345,您也可以运行此容器。 没有什么不愉快的事情发生。
如果容器依赖于可以从主机系统绑定安装的存储,情况会稍微复杂一些。 在这种情况下,容器进程的用户或组 ID 需要与可以写入主机目录的内容相匹配。 镜像无法知道主机特定的 uid 或 gid 是什么,因此您需要在运行容器时指定它。 同样,没有特别要求用户“存在”在任何地方;主机文件可能由任意数字 uid 拥有 (
sudo chown 9876 ./data/
)。