部署在Google Cloud Run的Node.js应用出现404文件未找到错误
解决Google Cloud Run部署Node.js/React应用的404错误
以下是针对本地运行正常、Cloud Run上出现404错误的排查与修复方案:
1. 确认部署包中的文件结构
Cloud Run的404问题常源于容器中缺少预期的静态文件或构建产物,需验证:
- 检查构建脚本(Cloud Build或本地脚本),确保React应用的
npm run build命令已执行,且superadmin/build、clubadmin/build、clubs-lp/dist这些构建目录已被包含在部署包中。 - 在Dockerfile中添加文件列表命令,查看容器内的文件结构:
RUN ls -R /app # 替换为你的容器工作目录 - 检查
.dockerignore文件,确保没有误排除build、dist或static-lp目录。
2. 修正Express路径解析逻辑
容器环境中__dirname的指向可能与本地不同,改用绝对路径解析避免歧义:
const express = require('express'); const path = require('path'); const app = express(); // 兼容Cloud Run动态端口分配 const PORT = process.env.PORT || 8080; app.use(express.json()); // 用path.resolve确保绝对路径正确 const superadminBuildPath = path.resolve(__dirname, './superadmin/build'); const clubadminBuildPath = path.resolve(__dirname, './clubadmin/build'); const clubcastLPBuildPath = path.resolve(__dirname, './static-lp'); const clubsLPBuildPath = path.resolve(__dirname, './clubs-lp/dist'); app.use('/superadmin', express.static(superadminBuildPath)); app.use('/clubadmin', express.static(clubadminBuildPath)); app.use(express.static(clubcastLPBuildPath)); app.use('/clubs', express.static(clubsLPBuildPath)); // 用root参数简化sendFile调用,避免路径错误 app.get('/clubadmin/*', function (req, res) { res.sendFile('index.html', { root: clubadminBuildPath }); }); app.get('/superadmin/*', function (req, res) { res.sendFile('index.html', { root: superadminBuildPath }); }); app.get('/clubs/*', function (req, res) { res.sendFile('index.html', { root: clubsLPBuildPath }); }); app.get('/*', function (req, res) { res.sendFile('index.html', { root: clubcastLPBuildPath }); }); app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); });
3. 适配Cloud Run的端口要求
Cloud Run会动态分配端口,必须监听PORT环境变量而非硬编码8080,否则容器无法接收请求,表现为404或503错误。上述代码已修正此问题:const PORT = process.env.PORT || 8080;
4. 检查React应用的静态资源路径
- 若React应用的
package.json中设置了homepage字段,需确保其与Express的路由前缀一致,例如:// superadmin/package.json { "homepage": "/superadmin" } - 为静态资源添加缓存控制,避免浏览器缓存旧资源导致的加载错误:
app.use('/superadmin', express.static(superadminBuildPath, { maxAge: '1y', etag: false }));
5. 验证Dockerfile配置
确保Dockerfile完整复制了所有依赖与产物,示例配置:
FROM node:18-alpine WORKDIR /app # 先复制package文件,利用Docker层缓存 COPY package*.json ./ RUN npm install --production # 复制项目文件 COPY . . # 构建React应用(若未在本地提前构建) RUN cd superadmin && npm install && npm run build RUN cd clubadmin && npm install && npm run build RUN cd clubs-lp && npm install && npm run build # 暴露端口(Cloud Run会忽略EXPOSE,但建议保留) EXPOSE ${PORT} # 启动服务器 CMD ["node", "server.js"]
内容的提问来源于stack exchange,提问作者Shiva C
相关产品推荐
相关产品推荐

