This workshop is a step-by-step guide to exploring the features of app services using a standard Node.js sample application.
This is based on our documentation here https://docs.microsoft.com/en-gb/azure/app-service/quickstart-nodejs?tabs=linux&pivots=development-environment-azure-portal
What this workshop demonstrates is how to:
- Create a web app in the Azure portal
- A tour of app services
- Create a sample app code on your machine (in Node.js)
- Deploy to your web app on Azure
- Validate it is working and inspect the deployed web app
- Demonstrate how to use deployment slots for blue/green deployments
- How to inject variables or secrets into your web app
- How to use key vault to store a secret that the web app then uses
- Access to an Azure subscription or resource group with contributor rights.
- Command line in Windows/WSL or a Mac (this guide will concentrate on Windows, but it should be very similar in Linux (WSL) or a Mac
- Visual Studio Code with the Azure Tools extension installed (this extension is published by Microsoft)
- A version of Node.js
It may be a little confusing, but web apps in Azure come under the product "app services". This is because, there are several types of web app, but they all use a common infrastrcture. So, if you hear app services on Azure - these are web apps. There are other means of hosting web apps, but app services is the main one and is the subject of this workshop.
You need to have:
- A globally unique name
- Choose Node as the runtime
- Your favourite Azure region
- A service plan of at least an S1 type (this will be needed for later stages)
Once deployed, your new app should have a holding page:
Spend some time looking at some of the features of the web app. A list of the more common ones is shown below:
The overview sestion shows some important values:
- URL - the URL of the web app
- the app service plan name with its SKU and number of instances. This is the compute that runs the web app
- Location - which region the web app runs in
- Resource group of the resource
- Publish profile - this downloads an XML file with the credentials that may be used to authenticate to publish an application into the web app
These are the web app metrics
As a service plan is the compute, this has metrics that are easy to understand like CPU percentage and memory used. These are shared across all apps that use that service plan.
A service plan is the compute for the web app. It will have a SKU and number of instances. Note that there are Windows and Linux service plans. A service plan can be either Windows or Linux. Not both.
There are two ways a service plan (and therefore all of the web apps in that plan) can scale - by selecting the SKU or type of underlying compute or the number of instances.
Scaling up is about changing the SKU for a different one. This is not generally ever done in production, but earlier in the lifecycle. Different SKUs have differing capabilities as well as performance. Scaling up generally will cause an interruption of service.
Scaling out is about changing the number of instances of a service plan. Increasing the number will generally increase the throughput of a web app. A web app meets the app service SLA with a single instance, but it is recommended to have 2 or more instances for production.
Scaling can be done manually or automatically - this can be configured here.
This displays a number of settings. The most interesting ones are:
- The runtime language and version
- Whether the web app will stay in memory or be moved out from inactivity
- ARR Affinity - whether the app service load balancer will route requests to the service plan instance that served the first request from that client. This uses a cookie.
These show some setting and connection strings that can be pushed down into the application. Thus enabling the removal of settings, credentials or secrets from the application code.
A mechanism to allow safe deployment mechanisms by creating a copy of the web app that can be used in load balanced requests. This can enable blue/green or canary deployments.
- Look at files
- Curl http://ifconfig.co for outbound IP address
- Nslookup
- Ping
For this we are using node to create an Express demo app.
- Open up a command prompt into a new working directory/folder - name it what you like
- Check that node is alive
node --version
- Create the Express app
npx express-generator myExpressApp --view pug
- This should have created an app in the folder myExpressApp
- cd to myExpressApp
- Build the app, getting its dependencies
npm install
- The application can be locally tested by:
npm start
- You should then see in a browser session at http://localhost:3000 the Express default page:
But this is only now running locally, so let's upload this to our previously created web app.
If you have Visual Studio Code (VSCode) installed, the simplest way of lauching it from the command line is to:
code .
You should then launch VSCode in the correct folder:
If you have the Azure extension installed, there should be an "A" icon down the left side of VSCode.
Click on it:
You should see your subscription and if you press the > arrow, it will then open and show a list of the web apps in that subscription.
- Choose your web app from the earlier step and right click
- choose the item "Deploy to Web App..."
- Pick "Yes" if it asks if you want to build on the web app
- Pick "Deploy" - if you are sure
- Wait until it completes.
For more explanation on what is happening above, the Azure app service can take deployments built elsewhere - in development environments or in DevOps pipelines or it can perform these build steps on its own. In this way, app services can work directly with code repositories. In general, it is more common for applications to be built externally and the pre-built artifacts to be deployed.
You can now go back to the Azure portal and on the Overview click the "URL"
which show show the web app exactly like it was when running locally.
Congratulations. You now have your app on Azure!
We now want to be able to deploy our application safely. Azure app services has the notion of deployment slots. These allow deployments to be made to another slot not directly impacting the main production web site. This is documented here https://docs.microsoft.com/en-us/azure/app-service/deploy-staging-slots
To use deployment slots, there are several stages:
- Create a deployment slot for our web application.
- Amend our application so this can represent a new version or release of our software
- Deploy this version to the deployment slot
- Either swap the slots - for a full deployment to the new version
- Or, only send a percentage of requests to the new slot - sometimes known as a canary release
- Show that a deployment can be backed-out by swapping the slots again
The web app has a section "deployment slots". Choose this and then "Add Slot"
You can name it anything you like, but staging is most meaningful in this context:
In VS Code amend your app and then save it.
This deploy is very similar to the previous deployment, but inside the Azure extension for VSCode, you navigate inside the web app using the > and then select your named slot (should be "staging")
Follow all of the questions until you can see that it has deployed.
This should be no different as you should have deployed to the staging slot only.
Choose swap and then on the confirmation dialog, press the swap button.
This can often take a minute or two. There then should be a confirmation - close the dialog.
Your application on the main URL should now look like this:
This is a little different to a slot swap, but what we intend here is to use both slots and get app services to push a percentage of requests to the staging slot and then the remainder to the main production slot.
This is done by choosing the main web application (not the staging one) and then alter the percentage to the staging and save.
Once this has completed, the web application will serve a ratio of requests from clients. So, in the case above 25% will go to the staging slot and 75% to the main production slot. This can be tested, but this is best in incognito/InPrivate sessions as once one client hits one of the slots, it is sticky.
This is straightfoward - it is essentially reversing the previous steps.
- If a full slot swap was done, then swap again
- If a canary style deployment, then you should then set the staging slot to now be 0%
Check this out for yourself by doing some experiments. It may be useful to use new browser sessions for each test.
This simplest route to injecting variables into your app code is to use environment variables these can be then set at a command prompt before running your app and the app can then be amended to pick up a value from an environment variable. App services uses this mechanism to allow you to set a variable in the Azure portal and for your application to the pick it up and use it.
The same mechanism may be used for secrets, such as connection strings to databases.
The steps are:
- create a variable in the app that picks up an environment variable
- Update the app to display the variable
- Test locally by injecting it
- Upload the app to Azure
- Add an "Application Setting" for that environment variable and set its value
- Validate that the application setting gets picked up by the application
This is only needed to be able to locally test the application before deployment. It will not get used by the app service, becasue it is local to your machine.
How to create an environment variable and set its value will depend on which operating system:
## Windows
set TITLE=john
## Linux
TITLE=john
Now let's use it.
You can do almost anything here, but a simple change to our sample application is to update its controller for its main route, so the file routes/index.js
var express = require('express');
var router = express.Router();
var titletext = process.env.TITLE
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: titletext });
});
module.exports = router;
This creates a variable titletext and sets its value to that of the environment variable TITLE.
You can run the application with:
npm start
Then validate that the output has changed
This is exactly the same process as earlier, going into VSCode and deploying the application from there.
But there's a problem! We have not set the environment variable for the web application. So let's do that next...
In an app service, the environment variables can be injected into the app runtime by values in Application Settings.
Go to Configuration/Application Settings and add a "New Application Setting" called "TITLE" and set its value:
Make sure to also hit "Save" after this dialog. It may also be necessary to Restart the web application after this
This is good, but if this varable is really a secret, such as a connection string, we can do better!
To recap so far. We have a web app deployed into app services and we can inject variables. Having these values set in Application Settings is much better than having these directly in code - especially so for secrets. But someone with access to the web application in the Azure portal could then read this value. Not ideal if this is a secret.
In this section, the plan is to use an Azure service called key vault to store a secret and then to configure the web app to use this value. Here are the steps we will go through:
- Create a key vault
- Create a secret of the same name as the environment variable from previous step (but different value)
- Enable the web app to access the KV by using managed identity (including RBAC to KV)
- Replace the application setting with a key vault reference
- Check application
- Look in Kudu at environment variables
Let's start.
A key vault is, like its name suggests, a place for holding secrets. A key vault is a separate Azure service that needs to be provisioned and later configured.
For the purposes of this workshop, we are going to create a key vault and just put a simple text value as a secret in the key vault. In normal use, user access to the key vault would be more restricted to enforce a division of responsibilities from those that create and manage secrets from those that either deploy or operationally manage applications.
Search for "key vault":
Choose key vault and Create:
There is not much interesting here. You need a unique name and you need to decide in which resource group and region for deployment. One choice is to put the key vault in the same resource group as the app and it is recommended this is in the same region.
Inside the key vault in the Azure portal, select *Secrets" on the left menu and then Generate/Import
Name your secret TITLE. It does not need to be named the same as the previous application setting, but I have named this for convenience. Don't forget to set a value for the secret too.
So, we now have a key vault and secret with a value.
Key vault is a separate service and an application needs to be able to access key vault. Key vault uses Azure AD to authenticate, so there needs to be an identity that can be used to access the key vault.
The simplest approach is to enable managed identity from the web app to give it an identity which key vault can use.
Go to the web app and find the identity menu. Enable the system assigned managed identity by pressing On and Save
This then creates and Azure AD identity for the application which the key vault will later be able to accept.
So, now we have an Azure AD identity that represents the application. Next to configure access from the web app to the key vault.
In the key vault, select Access Policies:
Next, press Add Access Policy:
Here, you are going to add an access policy of being able to read secrets. So choose secrets and in its dropdown, only select Get
Next press the line "none-selected for "Select Principal". A principal is essentially the user and this in our context is the managed identity of the web app we created earlier. So in the search list, search for the name of your web app (because the system assigned managed identity is named the same as the web app).
Then press Add to add this principal. Then press Save to Save this:
So, now we have a secret in key vault and our web application is allowed to read that secret. So, now we need to configure the web app to use that secret.
To allow a web app to use a key vault secret, there is a special syntax for an application setting that references the key vault. So instead of using the value of the application setting, it refers to a key vault.
The syntax is of the form below:
@Microsoft.KeyVault(SecretUri=https://your-key-vault-name.vault.azure.net/secrets/your-secret-name/)
So, in the web app, go back to Application Settings and replicate the value of the TITLE setting to the key vault reference. In the screen grab below, I have used "Advanced edit" and replaced the value of TITLE with the reference to key vault secret TITLE.
Once this has saved, you then should see something like below:
Notice, that the Source field has been replaced by "key vault Reference". After a few seconds, there should be a green tick on this. This indicates that the web app could reference the key vault secret. If this is in red, the you need to check your key vault reference.
Once complete, your application should display the new secret value from key vault.
Here, I chose a different name from that of the previous application setting for TITLE to make sure that it was being pulled from key vault.
Just to reiterate, key vault would normally be used for things like connection strings and these would not normally be displayed on the user interface.
Congratulations. The workshop is complete.
In this small workshop, we have built a small Node.js application and uploaded this to an Azure web application. We have seen how we can use the notion of deployment slots to do safe deployments of our web apps - either in blue-green mode or canary-style releases. We have also seen how variables can be injected into our web apps and how there Azure app service configures these. Finally, for secret variables, we have used Azure Key Vault to store a secret and how to configure the web app to make use of a key vault secret.
App services also has a rich set of other features that may also be easily used to enhance an application.