Deploying Your First Azure App Service: Step-by-Step

This page walks through creating an Azure App Service app from scratch and deploying a working web application to it. You will create a resource group, App Service Plan, and web app, then deploy a Node.js app using ZIP deployment. Each step explains what you are creating and why — not just what command to run.

What you need

  • Azure CLI installed and authenticated (az login)
  • A web application to deploy — this tutorial uses a simple Node.js Express app, but the steps apply to any supported runtime

If you need to install the CLI, see installing the Azure CLI. For App Service capabilities in general, see Azure App Service overview.

Step 1: Create a sample application

Create a minimal Node.js Express app to deploy. If you already have an app, skip this step.

mkdir my-azure-app && cd my-azure-app

# Create package.json
cat > package.json << 'EOF'
{
  "name": "my-azure-app",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.18.0"
  }
}
EOF

# Create the application
cat > app.js << 'EOF'
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({
    message: 'Hello from Azure App Service',
    env: process.env.NODE_ENV || 'development',
    timestamp: new Date().toISOString()
  });
});

app.listen(port, () => {
  console.log(`App running on port ${port}`);
});
EOF

npm install
Note

App Service sets the PORT environment variable to tell your application which port to listen on. Always read the port from process.env.PORT (Node.js), os.environ.get(‘PORT’) (Python), or the equivalent for your language. Your app will fail to receive traffic if it hardcodes a port other than what App Service assigns.

Step 2: Create the Azure resources

# Create a resource group
az group create \
  --name my-webapp-rg \
  --location eastus

# Create an App Service Plan (Standard S1 — supports autoscaling and slots)
az appservice plan create \
  --resource-group my-webapp-rg \
  --name my-app-plan \
  --sku S1 \
  --is-linux

# Create the web app (Node.js 20 runtime)
az webapp create \
  --resource-group my-webapp-rg \
  --plan my-app-plan \
  --name my-unique-webapp-$(date +%s) \
  --runtime "NODE:20-lts"

The —name must be globally unique across all of Azure — it becomes the subdomain of .azurewebsites.net. The $(date +%s) appends a timestamp to make it unique. Replace it with a meaningful name for real applications.

After creation, your app URL is https://<app-name>.azurewebsites.net. It currently shows a placeholder page because no code is deployed yet.

Step 3: Deploy your application

Package the application as a ZIP file and deploy it:

# From your app directory, create a ZIP excluding node_modules
zip -r app.zip . --exclude "node_modules/*" "*.git*"

# Deploy the ZIP to App Service
APP_NAME=$(az webapp list --resource-group my-webapp-rg --query "[0].name" --output tsv)

az webapp deployment source config-zip \
  --resource-group my-webapp-rg \
  --name $APP_NAME \
  --src app.zip

App Service extracts the ZIP, detects the Node.js application (via package.json), runs npm install, and starts your app using the start script. The deployment typically completes in 30–60 seconds.

# Open the app in a browser
az webapp browse --resource-group my-webapp-rg --name $APP_NAME

You should see the JSON response from your Express app. If the page shows an error, check the logs:

# Enable logging and stream real-time output
az webapp log config \
  --resource-group my-webapp-rg \
  --name $APP_NAME \
  --application-logging filesystem \
  --level information

az webapp log tail \
  --resource-group my-webapp-rg \
  --name $APP_NAME

Step 4: Configure environment variables

Set application settings that your app reads as environment variables:

az webapp config appsettings set \
  --resource-group my-webapp-rg \
  --name $APP_NAME \
  --settings \
    NODE_ENV=production \
    API_VERSION=v2 \
    LOG_LEVEL=info

After changing app settings, App Service restarts your app automatically to pick up the new values. You can verify they are set:

az webapp config appsettings list \
  --resource-group my-webapp-rg \
  --name $APP_NAME \
  --output table

App settings are encrypted in transit and at rest in Azure storage. However, they appear in plaintext in the portal. For sensitive values like database passwords, use Key Vault references — see Azure Key Vault overview.

Optional: Add a custom domain

The default domain (*.azurewebsites.net) works for testing, but production apps usually use a custom domain. App Service makes this straightforward:

# Add a custom domain to the web app
az webapp config hostname add \
  --resource-group my-webapp-rg \
  --webapp-name $APP_NAME \
  --hostname www.yourdomain.com

Before running this command, add a CNAME record in your DNS provider pointing www.yourdomain.com to $APP_NAME.azurewebsites.net. App Service verifies domain ownership by checking this DNS record.

For HTTPS on a custom domain, create a free managed certificate:

az webapp config ssl create \
  --resource-group my-webapp-rg \
  --name $APP_NAME \
  --hostname www.yourdomain.com

Alternative: az webapp up for rapid prototyping

For quick experiments, az webapp up creates all necessary resources and deploys in a single command:

cd my-azure-app

az webapp up \
  --name my-quick-app \
  --runtime "NODE:20-lts" \
  --sku F1 \
  --location eastus

This creates a Free tier App Service Plan (F1) and a web app, then deploys from the current directory. Free tier has no autoscaling, no custom domain SSL, and shared infrastructure — good for learning, not for production. After prototyping, migrate to Standard or Premium tier for production workloads.

Cleaning up

# Delete all resources in the resource group
az group delete --name my-webapp-rg --yes --no-wait

This deletes the web app, App Service Plan, and all associated resources. If you want to keep the App Service Plan and just stop the web app from billing, you can stop the app instead:

az webapp stop --resource-group my-webapp-rg --name $APP_NAME

A stopped App Service app still incurs Plan charges (you pay for the underlying compute tier of the plan), but the app itself consumes no additional resources. To fully stop billing, you need to delete the App Service Plan or scale it to Free tier.

Common first-deployment mistakes

  1. Using a globally non-unique app name. App Service app names must be unique across all of Azure. If your name is taken, the CLI returns an error. Use a prefix that includes your organisation name or a timestamp.
  2. Including node_modules in the ZIP. Uploading node_modules inflates the ZIP size from kilobytes to hundreds of megabytes. App Service runs npm install during deployment — exclude node_modules from the ZIP with —exclude “node_modules/*”.
  3. Not reading PORT from environment variables. App Service assigns a dynamic port via the PORT environment variable. An app that listens on port 3000 unconditionally will fail to receive traffic because App Service routes to the port it told the app to use, not 3000.

Frequently asked questions

Can I deploy a Python or Node.js app to App Service?

Yes. App Service on Linux supports Python, Node.js, Java, .NET, PHP, and Ruby natively. Specify the runtime version in the app settings. For Python, the recommended approach is to include a requirements.txt file — App Service detects it and runs pip install automatically during deployment. For Node.js, include a package.json and App Service runs npm install.

What is the difference between az webapp up and deploying manually?

az webapp up is an all-in-one command that creates a resource group, App Service Plan, and web app if they do not exist, then deploys your code. It is designed for rapid prototyping. For production, you typically create these resources separately with explicit configuration, then use az webapp deployment source or a CI/CD pipeline for deployments.

How do I see my app logs in real time?

Enable application logging first: az webapp log config --application-logging filesystem. Then stream logs: az webapp log tail. You see stdout and stderr from your application in real time. Logs are also available in the Azure portal under the Monitoring section of your web app.

Last verified: 19 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.