If you don’t want to manage a virtual machine and just want to take advantage of Azure’s salable web app infrastructure for running your node.js application then this post is for you
I’ve broken this guide into a few key areas of pain that I went through getting the configuration right and reliable.
- Commit your node_modules (*Your choice…but..)
- Express & IISNode
- Continuous Integration, SSH & Private Repositories
- Kudu is Kool
- Node versions
Commit your node_modules
I’ve tried pretty much every option that involved not committing your node_modules. This is where I’ve landed so let me explain the pros and cons
I’ll get the con out of the way right away. Yes, you’re committing all your dependencies, code you didn’t write, which will increase the size of your repository.
Now on the flip side lets go over the pros:
- Deployments are faster. You only have to deploy your repository and you’re done. No concerns with running npm install during a deployment and getting a untested version of a dependency.
- No concerns with network timeouts or latency when downloading thousands of additional files.
Just because you didn’t write it doesn’t mean you’re not responsible for it. At the end of the day it’s your application and you need to take ownership of all facets of it.
Express & IISNode
Azure WebApps come pre-installed with IISNode an open source IIS module allowing you to proxy connections from IIS to Node. Enabling this feature can be done by adding a web.config file to the root if your project with a couple lines of configuration.
If you’ve ever done Asp.net development then a web.config is pretty straight forward to you. But for the node.js folks the web.config is basically an xml based instructions for IIS and .net. In this case it’s going to tell IIS what to do with requests and how to route them into node.
Beware of named pipes. It’s important to know that because IIS is handling the requests on port 80 your node app is actually given a named pipe string for the port instead of a number and that is what IIS will proxy requests through.
Hope that gives you a good idea of how to configure Azure WebApps to run node.js and some of the initial brain teaser issues to solve.
<handlers> <-- Change path to the entry point of your application --> <add name="iisnode" path="index.js" verb="*" modules="iisnode" /> </handlers> <-- All of these properties can be overriden at the application level --> <iisnode node_env="development" loggingEnabled="true" debuggingEnabled="true" logDirectory="..\LogFiles\nodejs" promoteServerVars="HTTPS" enableXFF="true" />
Continuous Integration, SSH & Private Repositories
If you’re using GitHub you may be interested in doing continuous integration.
Using the Azure setup wizard for continuous integration against your repository will generate a SSH key on that repository. This grants this server access to pull from your repository if it’s public or private which is great. It will also add a web hook to kudu to notify the server when a push on your desired branch is done.
We now have continuous integration and deployment complete right? Well maybe…
Re-assigning SSH Keys
A nice touch of Kudu is that it will by default do a
git pull --recurse-submodules allowing you to pull any associated sub modules with your project as well. However because the SSH key is only assigned to the primary project you won’t be authorized to pull the sub modules by default.
You can get around this limitation by logging into your GitHub project and removing the SSH key auto generated by Azure. Then through the Kudu web interface path out to the .ssh directory, D:\home\.ssh and grab the public SSH key. Then add this key to your GitHub account instead of to a specific repository.
Kudu is Kool
Kudu is an open source interface for Azure WebApps that handles deployments and management of your application. It’s really awesome actually. But the primary pain comes during the deployment process.
During a deployment Kudu will launch a deploy.cmd batch script that you can alter to do any unique operations for your project before and after deployment.
Two primary issues you will run into
- npm install – If you didn’t follow my advice about node_modules then Kudu will have to do npm install causes it to make hundreds of requests to install node_modules.
- Kudu Sync – Is part of the Kudu deployment process. It’s job is to copy new or changed files. However it can easily become out of sync and mistakenly think it has already copied the file or it’s the same and not replace it.
Maybe I’m just lucky at hitting fringe cases immediately but with a real world project Kudu had my files out of sync after a couple deployments. The good news is because the Kudu deployment script is just a batch script we can do anything you can do with batch.
I’ve been a huge fan of robocopy for years and it’s my go to tool of choice when ensure files and folders are in sync.
rem call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 100 -f "%DEPLOYMENT_SOURCE%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd" call :ExecuteRoboCopy robocopy "%DEPLOYMENT_SOURCE%" "%DEPLOYMENT_TARGET%" /MIR /MT /R:100 /NDL /NP /NFL /XD ".git" /log:"D:\home\LogFiles\deployment.log"
Then you will have robocopy in charge of keeping your repository in sync with your wwwroot deployments.
You can configure Azure WebApps to use a specific of node by Application setting
WEBSITE_NODE_DEFAULT_VERSION to the version you desire. Not all versions are available. I recommend using the Kudu interface to path to D:\Program Files (x86)\nodejs to get a list of all the available versions.
Check out my next post on some advanced configurations and some additional recommendations.