本地Git部署Express至Azure App Service失败:依赖链接出错
问题:Express.js应用部署Azure App Service时依赖链接阶段失败
尝试通过本地Git将Express.js应用部署至Azure App Service,本地运行正常,但部署时在依赖链接阶段失败。应用使用80端口,部署未包含node_modules,public文件夹内有React构建产物。
部署日志
2024-06-08T19:51:30.752150035Z / _ \ __________ _________ ____ 2024-06-08T19:51:30.752154235Z / /_\ \\___ / | \_ __ \_/ __ \ 2024-06-08T19:51:30.752157335Z / | \/ /| | /| | \/\ ___/ 2024-06-08T19:51:30.752160335Z \____|__ /_____ \____/ |__| \___ > 2024-06-08T19:51:30.752163435Z \/ \/ \/ 2024-06-08T19:51:30.752166335Z A P P S E R V I C E O N L I N U X 2024-06-08T19:51:30.752169535Z 2024-06-08T19:51:30.752172235Z Documentation: http://aka.ms/webapp-linux 2024-06-08T19:51:30.752175535Z NodeJS quickstart: https://aka.ms/node-qs 2024-06-08T19:51:30.752178335Z NodeJS Version : v18.19.1 2024-06-08T19:51:30.752181035Z Note: Any data outside '/home' is not persisted 2024-06-08T19:51:30.752184035Z 2024-06-08T19:51:31.193914248Z Starting OpenBSD Secure Shell server: sshd. 2024-06-08T19:51:31.244489951Z Starting periodic command scheduler: cron. 2024-06-08T19:51:31.276188603Z Could not find build manifest file at '/home/site/wwwroot/oryx-manifest.toml' 2024-06-08T19:51:31.280345636Z Could not find operation ID in manifest. Generating an operation id... 2024-06-08T19:51:31.280378236Z Build Operation ID: 41e9c42e-d2f1-434c-a412-46c9c404420a 2024-06-08T19:51:31.485113164Z Environment Variables for Application Insight's IPA Codeless Configuration exists.. 2024-06-08T19:51:31.507160140Z Writing output script to '/opt/startup/startup.sh' 2024-06-08T19:51:31.544600937Z Running #!/bin/sh 2024-06-08T19:51:31.544629338Z 2024-06-08T19:51:31.544633938Z # Enter the source directory to make sure the script runs where the user expects 2024-06-08T19:51:31.544637538Z cd "/home/site/wwwroot" 2024-06-08T19:51:31.544640938Z 2024-06-08T19:51:31.544644138Z export NODE_PATH=/usr/local/lib/node_modules:$NODE_PATH 2024-06-08T19:51:31.544647438Z if [ -z "$PORT" ]; then 2024-06-08T19:51:31.544650738Z export PORT=8080 2024-06-08T19:51:31.544654538Z fi 2024-06-08T19:51:31.544657638Z 2024-06-08T19:51:31.544660738Z PATH="$PATH:/home/site/wwwroot" cd prodoslo1 && yarn install && yarn run prod 2024-06-08T19:51:31.955441605Z yarn install v1.22.15 2024-06-08T19:51:32.085875742Z [1/5] Validating package.json... 2024-06-08T19:51:32.089607272Z [2/5] Resolving packages... 2024-06-08T19:51:32.662441527Z [3/5] Fetching packages... 2024-06-08T19:51:52.373047412Z info fsevents@2.3.3: The platform "linux" is incompatible with this module. 2024-06-08T19:51:52.373369015Z info "fsevents@2.3.3" is an optional dependency and failed compatibility check. Excluding it from installation. 2024-06-08T19:51:52.395040552Z [4/5] Linking dependencies... 2024-06-08T19:51:53.245750111Z error Could not write file "/home/site/wwwroot/prodoslo1/yarn-error.log": "EROFS: read-only file system, open '/home/site/wwwroot/prodoslo1/yarn-error.log'" 2024-06-08T19:51:53.246134615Z error An unexpected error occurred: "EROFS: read-only file system, mkdir '/home/site/wwwroot/prodoslo1/node_modules'". 2024-06-08T19:51:53.246313917Z info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
package.json配置
"dependencies": { "@babel/cli": "^7.18.10", "@babel/core": "^7.18.13", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/polyfill": "^7.12.1", "@babel/preset-env": "^7.18.10", "@babel/register": "^7.18.9", "@sentry/node": "^7.58.1", "axios": "^1.3.5", "babel-plugin-dynamic-import-node-babel-7": "^2.0.7", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "date-fns": "^2.30.0", "debug": "^4.3.4", "dotenv": "^16.0.1", "exceljs": "^4.3.0", "express": "^4.18.1", "google-auth-library": "^8.9.0", "google-spreadsheet": "^4.0.2", "googleapis": "^120.0.0", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", "mathjs": "^11.11.1", "moment": "^2.29.4", "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", "mysql2": "^2.3.3", "node-cron": "^3.0.2", "nodemailer": "^6.9.1", "nodemon": "^2.0.19", "npm-run-all": "^4.1.5", "query-string": "^8.1.0", "rimraf": "^5.0.0", "sequelize": "^6.37.1", "socket.io": "^4.7.2", "swagger-autogen": "^2.23.7", "swagger-ui-express": "^5.0.0", "sweetalert2": "^11.6.10", "twilio": "^4.19.3", "uuid": "^9.0.0", "ws": "^8.15.1", "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.1/xlsx-0.19.1.tgz" }, "lint-staged": { "*.{js}": [ "yarn run format", "git add ." ] }, "devDependencies": { "@babel/plugin-syntax-import-assertions": "^7.22.5", "@babel/plugin-transform-modules-commonjs": "^7.22.5", "eslint": "8.22.0", "eslint-config-google": "^0.14.0", "husky": "^8.0.1", "jest": "^28.1.3", "lint-staged": "^13.0.3", "prettier": "^2.7.1" }, "jest": { "testEnvironment": "node" }
排查与解决方案
核心问题定位
日志中的错误EROFS: read-only file system, mkdir '/home/site/wwwroot/prodoslo1/node_modules'明确指向:Azure App Service的/home/site/wwwroot目录在运行时为只读状态,而部署脚本直接在此目录执行yarn install,尝试创建node_modules目录和写入日志文件,触发权限错误。
解决方案步骤
修改启动命令,将依赖安装到可写目录
Azure的/home目录是可持久化且具备写入权限的目录,可将依赖安装到该目录下。修改启动命令为:cd /home/site/wwwroot/prodoslo1 && yarn install --modules-folder /home/node_modules && yarn run prod或者通过指定工作目录的方式:
cd /home && yarn install --cwd /home/site/wwwroot/prodoslo1 && cd /home/site/wwwroot/prodoslo1 && yarn run prod配置NODE_PATH环境变量
在Azure门户的应用服务配置页面,添加环境变量:NODE_PATH=/home/node_modules
让Node.js能够找到安装在/home目录下的依赖包。
提前构建依赖,避免运行时安装
更高效的方式是在本地完成依赖安装和构建,再部署到Azure:- 本地执行
yarn install --production(仅安装生产依赖,减少体积) - 调整
.gitignore,允许提交node_modules目录(或针对部署分支单独配置) - 将包含
node_modules、应用代码、public构建产物的完整项目提交到Git,重新部署
- 本地执行
修正启动命令配置
若已提前安装依赖,可直接在Azure门户的"配置">"常规设置">"启动命令"中设置:cd /home/site/wwwroot/prodoslo1 && yarn run prod
额外注意事项
- 端口适配:Azure会动态分配端口,需确保Express应用监听
PORT环境变量而非硬编码的80端口,修改代码:const port = process.env.PORT || 80; app.listen(port, () => { console.log(`Server running on port ${port}`); }); - 可选依赖警告:日志中
fsevents的兼容性警告属于正常情况,该依赖为macOS专属,Linux环境下会自动跳过,不影响应用运行。
内容的提问来源于stack exchange,提问作者Thomas Rye
相关产品推荐
相关产品推荐

