为了安全起见,我应该以非 root 身份在 docker 容器内运行东西吗?

Gue*_*OCs 15 root docker

我已经运行了我的docker build并且docker run没有 sudo。但是,当我在 docker 容器内启动进程时,它top在主机上显示为根进程(不在容器内)。

虽然由于命名空间和来自 docker 的 cgroups 无法访问主机文件系统,但它是否仍然比以简单用户身份运行更危险?

如果是这样,以非 root 身份在 docker 内部运行事物的正确方法是什么?

我应该USER nonroot在 Dockerfile 的末尾做吗?

更新:

root 它也需要构建一些东西。我应该放在USERDockerfile的最上面,然后sudo与其他依赖项一起安装,然后sudo仅在构建中需要时使用吗?

有人可以在开始、安装和使用 USER 时给出一个简单的 Dockerfile 示例sudo吗?

the*_*ing 31

运行容器会root带来很多风险。尽管位于容器内部与在主机上root不同(此处有更多详细信息),并且您可以在容器启动期间拒绝许多功能,但这仍然是避免被推荐的方法。rootroot

USER通常,在安装一些通用包/库后,在 Dockerfile 中使用该指令是个好主意。换句话说 - 在需要root特权的操作之后。在生产服务映像中安装sudo是一个错误,除非您有充分的理由。在大多数情况下 - 你不需要它,这更多的是一个安全问题。如果您需要访问映像中某些特定文件或目录的权限,请确保您在 Dockerfile 中指定的用户确实可以访问它们(设置正确的uidgid其他选项,具体取决于您部署容器的位置)。通常您不需要事先创建用户,但如果您需要自定义内容,您始终可以这样做。

以下是在 user 下运行的 Java 应用程序的 Dockerfile 示例my-service

FROM alpine:latest
RUN apk add openjdk8-jre
COPY  ./some.jar /app/
ENV SERVICE_NAME="my-service"

RUN addgroup --gid 1001 -S $SERVICE_NAME && \
    adduser -G $SERVICE_NAME --shell /bin/false --disabled-password -H --uid 1001 $SERVICE_NAME && \
    mkdir -p /var/log/$SERVICE_NAME && \
    chown $SERVICE_NAME:$SERVICE_NAME /var/log/$SERVICE_NAME

EXPOSE 8080
USER $SERVICE_NAME
CMD ["java", "-jar", "/app/some.jar"]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我事先创建了用户并设置了它gid,禁用了它的 shell 和密码登录,因为它将成为“服务”用户。用户也成为 的所有者/var/log/$SERVICE_NAME,假设它将写入那里的一些文件。现在我们的攻击面要小得多。

  • @ChrisDanger 根据 https://wiki.alpinelinux.org/wiki/Setting_up_a_new_user '-S' 标志相当于 '--system'。 (2认同)

Cha*_*ens 10

为什么你不应该以 root 身份运行

虽然其他人指出您不应该以 root 身份运行映像,但这里或文档中没有太多信息说明原因。

虽然容器的 root 访问权限和主机的 root 访问权限之间确实存在差异,但容器的 root 访问权限仍然非常强大。

这是一篇非常好的文章,深入探讨了两者之间的区别以及这个问题的一般情况:

https://www.redhat.com/en/blog/understanding-root-inside-and-outside-container

总的一点是,如果你的容器中存在恶意进程,它就可以在容器中为所欲为,从安装包、上传数据、劫持资源,凡是你能想到的,它都能做。

这也使得进程更容易突破容器并获得主机上的特权,因为容器本身没有任何保护措施。

如何以及何时以非 root 身份运行

您想要做的是以 root 身份运行所有安装和文件下载/复制步骤(很多东西需要以 root 身份安装,一般来说,出于我在下面概述的原因,这只是一个更好的做法)。然后,显式创建一个用户并授予该用户运行应用程序所需的最低访问级别。这是通过使用chmodchown命令来完成的。

ENTRYPOINT在or指令之前CMD,您可以添加一个USER指令来切换到新创建的用户。这将确保您的应用程序以非根用户身份运行,并且该用户只能访问您在前面的步骤中明确授予其访问权限的内容。

一般的想法是,运行容器的用户应该拥有绝对最小的权限(大多数时候用户不需要对文件进行读、写和执行访问)。这样,如果您的容器中存在恶意进程,其行为将受到尽可能的限制。这意味着您应该避免创建或复制任何文件,或者也以该用户身份安装任何包,因为他们将完全控制默认创建的任何资源。我看到评论提出了相反的建议。别理他们。如果您想符合安全最佳实践,则必须返回并撤销用户的多余权限,这将是非常糟糕且容易出错的。

  • “这也使得进程更容易突破容器并获得主机上的特权,因为容器本身没有任何保护措施......” - 你能用例子来证明这一点吗? (6认同)