Azure容器部署Node.js Express服务后404及启动失败问题排查
问题
将基于TypeScript开发的Node.js+Express应用部署到Azure App Service后,出现以下异常:
- 访问
https://appurl/server-running端点返回404错误,但https://appurl/assets/img.png等静态资源、根路径页面可正常访问 - 配置
web.config试图通过iisnode将请求重定向到server.mjs,但未生效,且无法查看IISNODE日志 - 通过Kudu手动启动
node server.mjs后,访问端点仍返回404,Express服务无法自动启动,需手动调用 - 当前CORS设为
*,使用Azure免费层,无法在容器内安装内容,Node版本为v20.18.0
附相关配置片段:
package.json片段
"type": "module", "main": "server.mjs", "scripts": { "dev": "vite", "mainbuild": "tsc -b && vite build && npx tsc -b tsconfig.server.json", "build": " npm run mainbuild && npm run rename.mjs && npm run postbuild", "postbuild": "cp web.config dist/", "rename.mjs": "renamer --find '/\\.js$/' --replace '.mjs' './dist/*.js'", "lint": "eslint .", "preview": "vite preview", "start": "concurrently \"node server.mjs\" \"vite\"" }
web.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="iisnode" path="server.mjs" verb="*" modules="iisnode" resourceType="Unspecified" /> </handlers> <defaultDocument> <files> <clear /> <add value="server.mjs" /> </files> </defaultDocument> <iisnode> <nodeProcessCommandLine>node</nodeProcessCommandLine> <loggingEnabled>true</loggingEnabled> </iisnode> </system.webServer> </configuration>
server.ts(编译后重命名为mjs)
import express from "express"; import cors from "cors"; import {existsSync} from "fs"; const {FRONTEND_URL, EXPRESS_SERVER_CONFIG} = await import( existsSync("./config.ts") ? "./config.ts" : "./config.mjs" ); import JSONBig from "json-bigint"; const app = express(); app.use( cors({ origin: FRONTEND_URL, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], credentials: true, }) ); app.use(bodyParser.json()); app.get("/server-running", (req, res) => { console.log(req.baseUrl); res.send("Server is Running"); }); app.use((req, res) => { res.status(404).json({error: "404"}); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log( `Server is running on port ${PORT} front end url: ${FRONTEND_URL}` ); });
排查与解决方案
1. 修复Express服务启动错误
你的server.ts中使用了bodyParser.json()但未导入bodyParser模块,这会导致Node.js运行时抛出ReferenceError: bodyParser is not defined,服务根本无法正常启动。即使手动执行node server.mjs,服务也会崩溃,自然无法响应请求。
修复方法:
替换原有的bodyParser.json()调用为Express内置的JSON解析器(Express 4.16+已内置该功能):
// 替换原有的app.use(bodyParser.json()); app.use(express.json());
2. 完善web.config的URL重写规则
当前web.config仅配置了iisnode处理server.mjs文件,但没有将API请求转发到server.mjs。Azure App Service的IIS会优先处理静态资源,对于/server-running这类路径,IIS会当成静态文件查找,找不到就返回404,不会转发给Express服务。
修改后的web.config:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="iisnode" path="server.mjs" verb="*" modules="iisnode" resourceType="Unspecified" /> </handlers> <!-- 添加URL重写规则,将非静态资源请求转发给Express --> <rewrite> <rules> <!-- 排除静态资源路径,避免转发 --> <rule name="StaticFiles" stopProcessing="true"> <match url="^(assets|static)/.*$" /> <action type="None" /> </rule> <!-- 根路径指向前端首页 --> <rule name="Root" stopProcessing="true"> <match url="^$" /> <action type="Rewrite" url="index.html" /> </rule> <!-- 所有其他请求转发到server.mjs处理 --> <rule name="ExpressRoutes" stopProcessing="true"> <match url="(.*)" /> <action type="Rewrite" url="server.mjs" /> </rule> </rules> </rewrite> <defaultDocument> <files> <clear /> <add value="index.html" /> <add value="server.mjs" /> </files> </defaultDocument> <iisnode> <nodeProcessCommandLine>node</nodeProcessCommandLine> <loggingEnabled>true</loggingEnabled> <!-- 指定日志存储路径,方便后续排查 --> <logDirectory>iisnode</logDirectory> </iisnode> </system.webServer> </configuration>
3. 配置正确的启动命令
你的package.json中的start脚本是开发环境用的,同时启动node server.mjs和vite,生产环境不需要启动vite。Azure App Service默认执行npm start,需确保启动脚本仅运行Express服务,或直接在Azure门户配置启动命令。
两种配置方式:
- 修改
package.json的start脚本:"start": "node server.mjs" - 或在Azure门户的App Service -> 配置 -> 常规设置中,设置启动命令为:
注意:如果node server.mjsserver.mjs在dist目录下,启动命令应为node dist/server.mjs,同时需确保部署后的工作目录正确。
4. 确认部署文件结构
通过Kudu文件浏览器检查:
web.config位于部署根目录(或dist目录,需与Azure部署路径对应)server.mjs和静态资源文件路径正确- CI/CD部署时,确保部署的是
dist目录下的文件,而非项目根目录
5. 查看日志排查问题
无法查看IISNODE日志时,可通过以下方式获取日志:
- 在Azure门户的App Service -> 日志 -> 日志流中查看实时日志
- 通过Kudu访问
LogFiles/iisnode目录,查看iisnode日志文件 - 手动启动
server.mjs时,在Kudu CLI中查看输出的错误信息,确认服务是否正常启动
内容的提问来源于stack exchange,提问作者aamer saleem

