kudu: Zip deploy fails randomly on node_modules files for Linux web app
Repro steps.
I’m building a Nodejs 10.14 webservice using Azure Devops and deploying on Azure web app. It works in local or in Azure container, now i’m trying to deploy it in a classic Web App for the sake of simplicity.
Right now my Zip deploys are flaky, giving me errors 3 out of 4 times, always on node_modules files.
My webservice is a classic express backend. The bcrypt module is the only fancyness in it. I’m deploying a zip containing all node_modules installed and files built.
Project structures.
The closest boilerplate I could find : https://github.com/icebob/vue-express-sql-boilerplate
The log/error given by the failure.
~75% of my zip deployments including a node_module ends with an error on a random file:
2019-03-15T10:00:28.6009617Z Command: "/home/site/deployments/tools/deploy.sh"
2019-03-15T10:00:28.6010078Z Handling Basic Web Site deployment.
2019-03-15T10:00:28.6010454Z Kudu sync from: '/tmp/zipdeploy/extracted' to: '/home/site/wwwroot'
2019-03-15T10:00:28.6010711Z Copying file: '.dockerignore'
....
2019-03-15T10:00:28.6026397Z Copying file: 'dist/models/index.js'
2019-03-15T10:00:28.6026635Z Omitting next output lines...
2019-03-15T10:00:28.6026871Z Error: ENOENT: no such file or directory, utime '/home/site/wwwroot/node_modules/.bin/escodegen'
2019-03-15T10:00:28.6027124Z An error has occurred during web site deployment.
2019-03-15T10:00:28.6027354Z Kudu Sync failed
2019-03-15T10:00:28.6027580Z \n/opt/Kudu/Scripts/starter.sh "/home/site/deployments/tools/deploy.sh"
2019-03-15T10:00:28.6027824Z App container will begin restart within 10 seconds.
2019-03-15T10:00:28.6113580Z ##[error]Failed to deploy web package to App Service.
2019-03-15T10:00:28.6123485Z ##[error]Error: Package deployment using ZIP Deploy failed.
In the 5 failed deploy i had errors on: node_modules/.bin/uglifyjs
, node_modules/.bin/sshpk-conv
, node_modules/.bin/escodegen
Debug your Azure website remotely.
My sub is cb539346a and the site name qa***pi
Other informations
I also tried to exclude the node_modules and add npm install
in my post deployment steps. This doesn’t work as bcrypt fails to compile. I didn’t try much to make it work as I found documentation indicating the prefered way is to publish the node_modules folder.
Right now I find it hard to publish a node app on Azure, is anybody else experiencing this ?
Thanks all !
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 27
- Comments: 104 (17 by maintainers)
Have you tried
WEBSITE_RUN_FROM_PACKAGE=1
env var?It worked wonders for us (didn’t fix the symlink issue, but we circumvented that by specifying the full path.)
https://docs.microsoft.com/en-us/azure/azure-functions/run-functions-from-deployment-package#benefits-of-running-from-a-package-file
it says functions, but works with node on linux app service.
Azure Sucks… thats the problem. On AWS people can get work done plain and simple. Microsoft’s warped architectures does nothing but hold you back. Maybe we just need a few more layers of crap on top of the other layers of crap to fix it?
I’m pretty sure it’s connected with symlinks that are used in npm modules
@gecode-es Glad to hear it helped you!
Here is my understanding of azure web apps and kudu (I’m an azure customer, not an MSFT employee, so please correct me if any of these assumptions are wrong):
App Service runs kind of a docker container, however kudu sync treats the container as a mutable file system. That’s why at every deployment, you’re basically copying some of the files to the target file system. Also, you will see that if you create a file in the container, let’s say via
touch foobar
, that file will be preserved across deploys. So it does not start with a fresh container as in docker each time, it is more similar to how a normal machine would work, even though it is docker based.With this env var though, nothing gets copied except the zip file itself, which is mounted as a filesystem, therefore it is atomic (all or none)
With kudusync, when you deploy a node app, it looks at the timestamps of each file in your app and node_modules, determines which files are newer, and copies those. This is problematic in node ecosystem as some packages have been built such that their timestamp is a fixed point back in time (1985 specifically.) node guys do this for reproducible builds, but this confuses kudu sync as it thinks that those files are either too old or the same.
Therefore, in general, mutating the file system is very problematic and error proen and this flag makes it as if a layer (somewhat like a docker layer) consisting of the contents of the zip have been applied.
So, it is a very clean approach and works almost without issues.
One of the issues we ran into was the following though, when the very same container is accessed via kudu’s rest api, kudu sees the system as if that zip file has not been mounted. We were using kudu rest api to run some one of commands, but when kudu access the app service, the folder is blank since it is not mounted.
Another issue was that the symlinks inside node_modules/.bin were not proper, so to run a migration via sequelize for example, we had to do the following:
node node_modules/sequelize-cli/lib/sequelize db:migrate
normally,
npm run dbmigrate
which is specified assequelize db:migrate
would work, but doesn’t and fails with the following issue:Error: Cannot find module './core/yargs'
In general, I recommend
WEBSITE_RUN_FROM_PACKAGE=1
overall. One other benefit was that our deploys, which were taking 15-20 minutes due to node_modules now take 30-40 seconds.For people still running into this while trying to deploy a Node app from Github, I thought I’d add the easiest work around I’ve found.
I just created a
startup.sh
script in the root of my projects which runsnpm rebuild
to recreate all the node_modules symlinks followed by my actual project’s run command. I then go into the app service configuration in the Azure portal and change the custom startup command tostartup.sh
.This way the container will regenerate all of the symlinks before actually running your project. An example startup.sh script follows:
Hey guys,
we’re running Node JS application on the Linux machine (Azure Web App)
we’re using Travis CI to deploy to Azure Web Apps: https://docs.travis-ci.com/user/deployment/azure-web-apps/
It started to happen all of a sudden (the deployments worked up until 2nd October without problems)
Here are the logs:
The unsatisfiable solution is to SSH into the machine, cd into the
/home/site/wwwroot/
and remove wholenode_modules
folder (which is by the way present even though the Kudu sync command is complaining that the folder is missing) and rerun the Travis build (which is not how CI/CD should work)Can someone explain me what could happen on 2nd October or why it stopped working without any change to deployment configuration? (it doesn’t work till now - tried to create a new service - first deployment passed and the second immediately failed)
We found a few issues with ZipDeploy :
Symlinks problem: The files in node_modules/.bin are symlinks. Depending on how users produce the .zip file for their deployment, it is likely that those symlinks are not included in the zipfile. npm automatically adds the files in node_modules/.bin to the PATH so they can be used, so if they are not in the .zip file the scripts might stop working. We have fixed this issue on Kudu for Linux, this should be available in our next platform release. Kudu would now recognize symlinks and defer their creation until the complete zip file is extracted. KuduSync ran into issues when Kudu failed to create these symlink files. If you have sample apps where you run into this issue frequently, let us know we can add this to our tests.
EACCESS issue : some of the users experienced this as well, files did not have correct permissions. Zip deploy now ensures that all the extracted files have correct file permissions.
One other possible cause is that the app is running and locking the binaries : We are considering versioned deployments to fix this - We recommend using slots for active sites currently.
We recently changed the fflow of Kudu based Node deployments and we compress the node_modules directory and extract it locally during runtime/mount it in the memory as a read only volume. (We use Microsoft Oryx to build artifacts on Kudu for Linux) . You could enable Kudu to build artifacts by enabling the app setting SCM_DO_BUILD_DURING_DEPLOYMENT= true. Or you could use RUN_FROM_PACKAGE feature, zip gets mounted on wwwroot as a read-only file system.
@pat-flew we don’t extract the zip package and recreate the symlinks. We use fuse-zip file system to mount this zip, when the app is run using RunFromPackage
I am having a similar issue when using
WEBSITE_RUN_FROM_PACKAGE=1
. Some of the symbolic links are not being set correctly during deploymente.g.
/node_modules/html-webpack-plugin/node_modules/loader-utils/node_modules/.bin/json5
is being linked to
../../../json5/lib/cli.js
where it should be
../../../../../json5/lib/cli.js
consequently, the deploy fails with
Error: ENOENT: no such file or directory, stat '/home/site/wwwroot/node_modules/html-webpack-plugin/node_modules/loader-utils/node_modules/.bin/json5'
@ustun some great insight thanks for taking the time to explain your understanding and experience. Really appreciated.
@sanchitmehta Unfortunately, this hasn’t been fixed for node_modules. Just tried it again. Note the timestamp from the logs.
2019-10-22T16:46:42.9510471Z Error: EACCES: permission denied, mkdir ‘/home/site/wwwroot/node_modules/.bin’ 2019-10-22T16:46:42.9510611Z \n/opt/Kudu/Scripts/starter.sh kudusync -v 50 -f /tmp/zipdeploy/extracted -t /home/site/wwwroot -n /home/site/deployments/ca89f0184d7a41d5bd84e8218c8bfe4b/manifest -p /home/site/deployments/1ca21aa686af4aac9cfa661a145b4e77/manifest -i “.git;.hg;.deployment;.deploy.sh”
@nshumoogum We are looking at your app. @superfliege We have fixed this for the next Kudu Version. This fix would be a part of our next milestone which would start deploying in a week.
If you’re using Zip Deploy, a work around is to use Run From Package : Enable it by setting the app setting
WEBSITE_RUN_FROM_PACKAGE=1
Same issue here for past week.
Error: EACCES: permission denied, mkdir ‘/home/site/wwwroot/node_modules/.bin’
Been using Azure for both .NET Core and Node projects for a few years now and I’ve never had any confidence in the services. I always deploy and worry that tomorrow something will break and I’ll find myself in a world of hell again. This latest issue is the final straw I think. 😦 my life is complicated enough without this nonsense.
@sanchitmehta Any update on the investigation of this? I encountered this issue last week and can’t seem to find a resolution. Switching to the Windows App Service isn’t an option for my current project, unfortunately.
I’ve had so much trouble with Azure App Service on Linux. It’s not a great experience setting up a node app there compared to deploying a .net application on a Windows service. I’m kind of upset about how much time I’ve wasted on this (I usually wouldn’t express this on a GitHub issue, but it’s a paid product). I’m concerned about what issues I may encounter in the future if setup was this bad.
For this specific problem I encountered, I managed to workaround this after a lot of trial and error.
Problem 1: After doing a deploy with symlinks, any deploy I tried after even without symlinks would fail, and web ssh didn’t work. Was getting a
EHOSTUNREACH
error. Solution: Open up the App Service in the portal, Development Tools -> Advanced Tools, then click on the “Bash” tab. For me, that worked for some reason and I was displayed a prompt. From there I was able torm -rf
the contents of the/home/site/wwwroot
folder.Problem 2: Since a deploy with symlinks wrecked the server, what could be done to not deploy a zip with symlinks? Solution: I tried a lot of different things (including different deployment strategies) and ran into so many different problems. The only thing that ended up working for me was to delete all the symlinks and copy the target of the symlink to where the symlink used to be, then zip the folder for deployment to the server. This wasn’t a big issue for me to do since the size of the files was small.
I used this powershell script in my azure pipeline to do this:
@ustun - i am embarrassed, yes this worked for me; i should have double checked the variable name
Thanks everyone who tried to help me 😃
@nshumoogum WEBSITES_RUN_FROM_PACKAGE should be WEBSITE_RUN_FROM_PACKAGE
node_modules is locked and can’t be deleted via SSH or Bash on Linux machine 😦 swapping slot with an empty one deletes everything, here is my workaround for Node app zip deploy
az webapp deployment slot create --name YOURAPP --resource-group YOURGROUP --slot temp
az webapp deployment slot swap -g YOURGROUP -n YOURAPP --slot temp --target-slot Development
az webapp deployment slot delete --name YOURAPP --resource-group YOURGROUP --slot temp
works like a charm
@sanchitmehta Had the same as error @nshumoogum with a python app failing because of symlinks. Adding the ‘–copies’ option to venv creation fixed it! Hopefully adding WEBSITE_RUN_FROM_PACKAGE will add some consistency as well with other issues for us. Thank you and thanks for the transparency on these issues.
@nshumoogum If you’re using Python 3 and creating the environment yourself you could try adding –copies :
python -m venv antenv --copies
.From your logs it doesn’t look like Run From package is enabled and Kudu is trying to do a normal zip deployment and extracting the node_modules. Could you please check the Kudu Environment page, if the app setting
WEBSITE_RUN_FROM_PACKAGE=1
is present and then redeploy.@willmtemple this could also be that a different user (kudu runs as a dedicated user/group) that is creating installing npm modules in the pipeline and kudu user does not have access to override them. You could add
npm config set unsafe-perm=true
to allow all users to override these files.Ideally you should have a build step when you zip everything and use that during release (deploy) stage, otherwise it will be flaky. Also you should not use
npm install
butnpm ci
sincenpm install
does not honorpackage-lock.json
.Same issue. Deploying node app to Web App service on Linux stopped working recently. Zip deploy fails
Error: EACCES: permission denied, mkdir ‘/home/site/wwwroot/node_modules/.bin’
is this Azure issue or kudu? Any ETA on fix?
No real issues with .NET Core till now but this past week makes me wonder how much Microsoft ❤️ Linux at all. Very frustrating.
👍 same issue here with nodejs express app deployed by github repository
facing same issue via Local Git deploy - EAST US + EAST US 2 regions. @sanchitmehta Is there an update for my region??
@sanchitmehta Thanks for the update
For others, we’ve been able to work around this until the fix is in place by deleting out the
/home/site/wwwroot/node_modules
folder by runningrm -rf node_modules
from the wwwroot dirIt seems I have exactly the ZipDeploy Symlinks problem. Currently I can’t publish my node app on Linux. RUN_FROM_PACKAGE is not available on Linux. FTP upload would take over a day. When will this be fixed?
I was having a similar problem with a PHP project that is using composer:
I had to remove the folders with symlinks from the zip package:
I am having this exact same issue, and none of the suggestions are working for me. I suspect it has to do with Symlinks as well, but I can’t confirm that.