K3d集群中Node.js应用Pod使用PM2 Runtime启动时出现文件系统权限及文件缺失错误求助
看起来你的问题核心是PM2默认尝试在容器的根目录创建/.pm2目录,但Kubernetes(包括k3d)环境下容器的根文件系统通常是只读的,这直接导致了权限错误,进而引发后续的配置文件缺失问题。之前在Hetzner的k3s集群能正常运行,可能是当时的容器配置或PM2版本细节有差异,不过我们可以通过以下步骤快速解决:
一、核心解决方案:指定PM2到可写目录工作
PM2默认会在根目录(/)下生成.pm2文件夹存储配置、PID文件等,但容器根目录是只读的。我们可以通过设置PM2_HOME环境变量,让PM2把配置文件存储到容器的工作目录(/usr/app)下——这个目录默认是可写的。
修改你的Dockerfile,添加指定PM2工作目录的环境变量:
FROM node:18.3.0 WORKDIR /usr/app # 关键:指定PM2的配置存储目录到工作目录下的.pm2 ENV PM2_HOME=/usr/app/.pm2 COPY ./ package.json ./ ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true RUN npm install pm2 --location=global RUN npm install COPY ./ ./ ENV CI=true ENV WDS_SOCKET_PORT=0 CMD ["pm2-runtime", "server.js"]
二、可选但推荐:确保目录权限
如果你的容器使用非root用户运行(node:18.3.0镜像默认是node用户),可以提前创建.pm2目录并设置权限,避免启动时的权限问题:
在Dockerfile的npm install步骤之后添加:
RUN mkdir -p /usr/app/.pm2 && chown -R node:node /usr/app/.pm2 # 可选:切换到node用户运行容器,进一步提升安全性 USER node
三、额外排查点:检查Kubernetes Pod配置
如果你的Pod YAML中设置了readOnlyRootFilesystem: true,需要确认工作目录所在的挂载是否为可写状态。默认情况下Docker的WORKDIR在容器的可写层,无需额外挂载卷,但如果工作目录挂载了只读的ConfigMap/Secret,就要调整挂载路径,避免覆盖工作目录的可写权限。
补充说明
你提到在容器内手动启动pm2没问题,这大概率是因为exec进入容器后用的是root用户——root拥有根目录的写入权限,能创建/.pm2文件夹,但容器启动时默认用的是node用户,没有根目录的写入权限,所以启动失败。
备注:内容来源于stack exchange,提问作者Vincenzo

