简体   繁体   English

Docker 文件非 root 用户理论问题

[英]Docker File Non Root User Theory Question

I've been reading today on the theory behind uid 1001 specifically in Docker where it is a best principle not to have your container running as the root user.我今天一直在阅读 uid 1001 背后的理论,特别是在 Docker 中,最好的原则是不要让容器以 root 用户身份运行。

What I've been able to tell so far for a unix system is...到目前为止,对于 Unix 系统,我能说的是......

  • root user has the UID of 0 Most unix distributions reserve the first root 用户的 UID 为 0 大多数 unix 发行版保留第一个
  • 100 New users are assigned UIDs starting from 500 or 1000 100 个新用户被分配了从 500 或 1000 开始的 UID
  • When you create a new account, it will usually be give the next-highest unused number of 1001 (not sure what this means in relation to the previous dot point. If someone could clarify please)当您创建一个新帐户时,通常会给出次高的未使用数字 1001(不确定这相对于前一个点是什么意思。如果有人可以澄清,请)

I've seen a lot of Dockerfile examples that will just try to use 1001.我看过很多 Dockerfile 示例,它们只是尝试使用 1001。

USER 1001

Two questions两个问题

Is the theory 1001 is safe to use because it is above the uid allocations ranges for new users on the host ie dot point 2?理论 1001 是否可以安全使用,因为它高于主机上新用户的 uid 分配范围,即点 2?

Is it best practice to specify user as 1001 or would it be best adding a new user?将用户指定为 1001 是最佳做法还是最好添加新用户?

RUN useradd -ms /bin/bash newuser
USER newuser
WORKDIR /home/newuser

thank you谢谢你

If your container doesn't need to write data in a named volume or a directory bind-mounted from the host, it usually doesn't matter at all what user ID the container runs as.如果您的容器不需要在命名卷或从主机绑定挂载的目录中写入数据,则容器运行的用户 ID 通常完全无关紧要。 There are a couple of restrictions still (if you're trying to listen on a port number less than 1024 your user ID must be 0 or you must manually add a capability at startup time).仍然存在一些限制(如果您尝试侦听小于 1024 的端口号,则您的用户 ID 必须为 0,或者您必须在启动时手动添加功能)。

I would use your second form, except I would not switch users until the end of the Dockerfile.我会使用你的第二种形式,除非我不会在 Dockerfile结束之前切换用户。

FROM python:3.8 # arbitrary choice
# ... install OS packages ...

# Create the user.  This doesn't need to be repeated if the
# application code changes.  It is a "system" user without
# a home directory and a default shell.  We don't care what
# its numeric user ID is.
RUN useradd -r newuser

# WORKDIR creates the directory.  It does not need to be
# under /home.  It should be owned by root.
WORKDIR /app

# Copy the application in and do its installation, still as root.
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .

# Switch USER only at the end of the file.
USER newuser
CMD ["./app.py"]

"Home directory" isn't usually a well-defined concept in Docker; “主目录”在 Docker 中通常不是一个明确定义的概念; I've created the user without a specific home directory here, and the application directory isn't under the normal Linux /home directory.我在这里创建了没有特定主目录的用户,并且应用程序目录不在正常的 Linux /home目录下。 Similarly, I haven't gone out of my way to specify a shell for this user or to specifically use GNU bash.同样,我也没有特意为这个用户指定一个 shell 或专门使用 GNU bash。

One important security point of this setup is that root owns the application files, but newuser is running the code.此设置的一个重要安全点是root拥有应用程序文件,但newuser正在运行代码。 If there is some sort of compromise, this gives you an additional layer of protection: the compromised application code can't overwrite the application code or its fixed static data.如果存在某种损害,这将为您提供额外的保护层:受到损害的应用程序代码无法覆盖应用程序代码或其固定的静态数据。


I started this with the caveat that this works fine if you don't need to persist data in the filesystem.我开始时警告说,如果您不需要在文件系统中保留数据,这可以正常工作。 If it does it will need to be somewhat adaptable, which probably means starting up as root but then dropping privileges.如果是这样,它需要有一定的适应性,这可能意味着以 root 身份启动,然后放弃特权。 I'd support two modes of running:我会支持两种运行模式:

  1. The container is started up initially with a totally empty directory, possibly owned by root (a named Docker volume; a Kubernetes named volume).容器最初以一个完全空的目录启动,可能由 root 拥有(一个命名的 Docker 卷;一个 Kubernetes 命名的卷)。 In this case, create the data directory you need and make it owned by the user in the Dockerfile.在这种情况下,创建您需要的数据目录并使其归 Dockerfile 中的用户所有。

     docker run -v somevolume:/data myimage
  2. The container is started up with a bind-mounted host directory and also a -u option naming the host user ID to use.容器启动时带有一个绑定挂载的主机目录,还有一个-u选项,用于命名要使用的主机用户 ID。

     docker run -u $(id -u) "$PWD/data:data" myimage

You would need to use an entrypoint wrapper script to detect which case you're in, create the initial storage structure, set its permissions, and switch to a non-root user if required.您需要使用入口点包装器脚本来检测您所处的情况,创建初始存储结构,设置其权限,并在需要时切换到非 root 用户。 There are lighter-weight tools like gosu or su-exec that specifically support this case.有更轻量级的工具,如gosusu-exec ,专门支持这种情况。 The Docker Hub consul image's entrypoint script has an example of doing this at startup time . Docker Hub consul映像的入口点脚本有一个在启动时执行此操作的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM