在 OpenShift 容器中创建目录时出现“permission denied”的错误提示。

19

我有一个使用Node.js和pm2作为启动命令的容器,在OpenShift上启动时出现如下错误:

Error: EACCES: permission denied, mkdir '/.pm2'

我在Marathon上尝试相同的镜像,它可以正常工作。

我需要更改用户ID吗?

Dockerfile:

FROM node:7.4-alpine

RUN npm install --global yarn pm2

RUN mkdir /src

COPY . /src

WORKDIR /src

RUN yarn install --production

EXPOSE 8100

CMD ["pm2-docker", "start", "--auto-exit", "--env", "production", "process.yml"]

更新
节点镜像已经创建了一个新的用户"node",UID为1000,以便不以root身份运行该镜像。
我还尝试修复权限并将用户"node"添加到root组中。
此外,我使用环境变量告诉pm2应该使用哪个目录:

PM2_HOME=/home/node/app/.pm2

但我仍然遇到错误:

Error: EACCES: permission denied, mkdir '/home/node/app/.pm2'

更新后的Dockerfile:

FROM node:7.4-alpine

RUN npm install --global yarn pm2

RUN adduser node root
COPY . /home/node/app
WORKDIR /home/node/app
RUN chmod -R 755 /home/node/app
RUN chown -R node:node /home/node/app

RUN yarn install --production

EXPOSE 8100

USER 1000

CMD ["pm2-docker", "start", "--auto-exit", "--env", "production", "process.yml"]

更新2感谢Graham Dumpleton,我已经使它工作了

FROM node:7.4-alpine

RUN npm install --global yarn pm2

RUN adduser node root
COPY . /home/node/app
WORKDIR /home/node/app

RUN yarn install --production

RUN chmod -R 775 /home/node/app
RUN chown -R node:root /home/node/app

EXPOSE 8100

USER 1000

CMD ["pm2-docker", "start", "--auto-exit", "--env", "production", "process.yml"]

哪一行 RUN 命令导致了这个错误?编辑:啊,抱歉,这是在运行容器时发生的... - Alexander Block
看起来pm2-docker忽略了当前的工作目录。同时,通过检查镜像历史记录(我找不到7.4的Dockerfile),预期的工作目录似乎是/home/node。可能pm2-docker(从未使用过)也期望这是工作目录。您能否尝试更改COPY和WORKDIR,使源位于/home/node内? - Alexander Block
Dockerfile 应该是这样的:https://github.com/nodejs/docker-node/blob/90d5e3df903b830d039d3fe8f30e3a62395db37e/7.5/alpine/Dockerfile - ivoba
我其实在想,我是否需要 PM2,因为容器会在节点进程崩溃时自动重启,不是吗? - ivoba
创建镜像的机器上内核版本为4.4.0-63-generic,存储驱动程序为:Storage Driver: aufs。 - ivoba
显示剩余2条评论
5个回答

20

OpenShift默认会使用非root用户运行容器。因此,如果您的应用程序需要以root身份运行,则可能会失败。是否可以配置容器以root身份运行取决于您在集群中拥有的权限。

最好设计您的容器和应用程序,使其不必以root身份运行。

以下是一些建议。

  • 创建一个专用的UNIX用户来运行应用程序,并将该用户(使用其uid)设置为Dockerfile中USER语句的用户。将用户的组设置为root组。

  • 修复/src目录及其所有子目录的权限,以使其归专用用户所有。确保所有内容均为根组。确保任何需要可写的内容都可以由根组进行写入。

  • 确保在Dockerfile中将HOME设置为/src

这样做后,当OpenShift将您的容器作为指定的uid运行时,由于所有内容均为组可写,应用程序仍然可以更新/src下的文件。设置HOME变量可确保代码写入home目录的任何内容都进入可写的/src区域。


我尝试使用了你所有的建议,但仍然失败了,请查看更新后的问题。 - ivoba
除了你没有完全正确。chmod 应该是 775,chown 应该是 node:root。并且在所有其他命令运行之后执行此操作,因此在 yarn install 之后执行,以防它写入工作目录。 - Graham Dumpleton
@GrahamDumpleton:在这种情况下,用户(即node)需要同时存在于主机上还是只需要在Dockerfile中指定? - grizzthedj
node 用户需要在容器镜像的 /etc/passwd 中存在。它不需要存在于底层的 OpenShift 节点主机上。 - Graham Dumpleton
1
第一步,“创建一个特殊的UNIX用户来运行应用程序,并在Dockerfile的USER语句中设置该用户(使用其uid)”,是毫无意义的。除非您深入了解Openshift的设置并进行更改,否则Openshift不允许自定义用户。话虽如此,所有授予DockerImages的用户都在root组内,因此这些说明仍然有效,尽管是无意中的。 - Eliezer Berlin

5

您还可以运行以下命令,以授予当前登录项目的 root 访问权限:

oc adm policy add-scc-to-user anyuid -z default


如果您正在使用需要root访问权限才能运行的预打包镜像,则此解决方案正是您所需的。 - Kuthumi Pepple

0

Graham Dumpleton的解决方案虽然可行,但不建议使用。

Openshift在运行容器时会使用随机UID。

您可以在Pod的生成Yaml中看到这一点。

spec:
    - resources:
      securityContext:
        runAsUser: 1005120000

你应该使用Docker安全最佳实践来编写你的Dockerfile。

  1. 不要将应用程序的执行绑定到特定的UID:当需要时,使资源可读(即0644而不是0640)和可执行。

  2. 使可执行文件归属于root而不可写

有关完整的建议列表,请参见:https://sysdig.com/blog/dockerfile-best-practices/

在你的情况下,没有必要:

RUN adduser node root
...
RUN chown -R node:node /home/node/app
USER 1000

在原始问题中,应用程序文件已经被root所有。
以下的chmod足以使它们对世界可读和可执行。

RUN chmod -R 775 /home/node/app

0

默认情况下,OpenShift容器平台使用任意分配的用户ID运行容器。这提供了额外的安全性,防止由于容器引擎漏洞而导致进程逃逸容器,并在主机节点上获得升级的权限。

为了支持以任意用户身份运行镜像,图像中由进程写入的目录和文件必须属于根组,并且该组必须具有读/写权限。要执行的文件还必须具有组执行权限。

将以下内容添加到您的Dockerfile中,可以设置目录和文件权限,以允许根组中的用户在构建的镜像中访问它们:

RUN chgrp -R 0 /some/directory && \
    chmod -R g=u /some/directory


WORKDIR /some/directory

由于容器用户始终是root组的成员,因此容器用户可以读写这些文件。

https://docs.openshift.com/container-platform/4.11/openshift_images/create-images.html#use-uid_create-images


下面是Docker文件中如何使用的示例:

# Add non-root user (with home dir at /opal)

RUN useradd -m -b / -s /bin/bash opal

RUN chgrp -R 0 /opal && \
    chmod -R g=u /opal

WORKDIR /opal

这样你就可以作为opal用户运行程序,但是WORKDIR /opal的组却是root。


-4
你使用的是哪种OpenShift?
你可以编辑“限制性”安全上下文约束:
从OpenShift CLI:
oc edit scc restricted 

并将其更改为:

runAsUser:
  type: RunAsUSer

runAsUser:
  type: RunAsAny

请注意,Graham Dumpleton的回答是正确的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接