为了安全起见,我是否应该 运行 在 docker 容器中作为非 root 用户?

Should I run things inside a docker container as non root for safety?

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

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

如果是这样,运行将 docker 中的东西作为非 root 的正确方法是什么?

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

更新:

root 它也需要构建一些东西。我是否应该将 USER 放在 Dockerfile 的最顶部,然后将 sudo 与其他依赖项一起安装,然后仅在构建中需要时才使用 sudo

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

您可以查看 Docker 的 CIS 基准,他们建议使用非 root,这是“合规性”检查之一。在底部添加 USER non-root 就足够了,或者您也可以在 运行 命令中使用“-u”来指定用户。

https://www.cisecurity.org/benchmark/docker/ https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

运行容器作为root带来了很多风险。尽管在容器内 root 与主机上的 root 不同(在容器启动期间有更多细节 here) and you're able to deny a lot of capabilities,但仍然推荐避免被 root.

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

这是在用户 my-service 下运行的 Java 应用程序的 Dockerfile 示例:

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"]

如您所见,我预先创建用户并设置其 gid,禁用其 shell 和密码登录,因为它将成为 'service' 用户。用户也成为 /var/log/$SERVICE_NAME 的所有者,假设它将写入那里的一些文件。现在我们的攻击面小了很多。

为什么你不应该 运行 作为 root

虽然其他人指出您不应该 运行 图像作为 root,但这里或文档中没有太多关于为什么会这样的信息。

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

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

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

总的来说,如果你的容器中有恶意进程,它可以在容器中为所欲为,从安装包、上传数据、劫持资源,你说的出来,它都能做到。

这也使得进程更容易突破容器并获得主机特权,因为容器本身没有安全措施。

如何以及何时 运行 作为非 root

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

紧接着您的 ENTRYPOINTCMD 指令,然后添加一个 USER 指令以切换到新创建的用户。这将确保您的应用程序 运行 作为非 root 用户使用,并且该用户将只能访问您在前面的步骤中明确授予其访问权限的内容。

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

运行 您的非 root 容器为您提供了额外的安全层。默认情况下,Docker 容器是 运行 作为根,但这允许不受限制的容器活动。