我正在使用Docker设置Golang服务器,为了安全起见,我希望没有特权的用户在其容器内启动它。
这是我使用的简单Dockerfile。我将二进制文件导入容器并设置一个随机UID。
FROM scratch
WORKDIR /app
COPY --chown=1001:1001 my-app-binary my-app-binary
USER 1001
CMD ["/app/my-app-binary"]
如果我的服务器侦听端口443,则它不起作用,因为它需要特权权限。因此,我的应用程序按预期由非特权用户运行。
尽管如此,未正确创建用户1001。我看到的教程告诉我要在一个中间“构建器”容器(例如,alpine)中创建用户,并从中导入/ etc / passwd。我没有发现做我的工作的任何例子。 (here我遵循了一个教程)
有人可以向我解释为什么我的解决方案有效或我不理解吗?
答案 0 :(得分:2)
披露:在我的回答中,我使用了this blog post中的引号。我既不是本文的作者,也不是与作者相关的任何人。
可以预料-容器可以在容器未知的用户下运行。引用docker run
docs:
root
(id = 0)是容器中的默认用户。图像开发人员可以创建其他用户。这些用户可以通过名称访问。 传递数字ID时,用户不必在容器中。
它可以帮助您解决以下问题:
有时候,当我们在Docker容器中运行构建时,构建会在从主机(例如源代码目录)将其安装到容器中的文件夹中创建文件。这会给我们带来痛苦,因为这些文件将由
root
用户拥有。当普通用户在准备下一个版本时尝试清理这些文件时(例如,使用git clean
),他们会收到错误消息,并且我们的版本将失败。-https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15#7d3a
这可能是因为:
幸运的是,
docker run
为我们提供了一种方法:the --user parameter。我们将使用它来指定Docker应该使用的用户ID(UID)和组ID(GID)。之所以可行,是因为Docker容器都共享相同的内核,因此也共享相同的UID和GID列表,即使容器不知道相关的用户名(稍后会详细介绍)。-https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15#b430
以上内容也适用于USER dockerfile command。
使用容器未知的UID有一些陷阱:
您的用户将少$ HOME
我们在这里实际要做的是让我们的Docker容器使用一无所知的用户ID进行操作,这会带来一些麻烦。也就是说,这意味着用户正在丢失一些我们已经学到的仅希望用户拥有的东西-诸如主目录之类的东西。这可能很麻烦,因为这意味着$ HOME $中的所有内容(包括临时文件,应用程序设置,程序包缓存)现在都无处可住。容器化过程只是无法知道将它们放在哪里。
当我们尝试做特定于用户的事情时,这可能会影响我们。我们发现使用
gem install
会导致问题(尽管使用Bundler可以),或者运行依赖于ENV['HOME']
的代码。因此,这可能意味着您需要做一些调整。您的用户也将是匿名的
事实证明,我们无法轻松地在Docker主机及其容器之间共享用户名。这就是为什么我们不能只使用
docker run --user=$(whoami)
的原因-容器不知道您的用户名。它只能通过其UID来找到有关您用户的信息。这意味着当您在容器中运行
whoami
时,将得到类似I have no name!
的结果。这很有趣,但是如果您的代码依赖于知道您的用户名,那么您可能会得到一些令人困惑的结果。-https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15#e295