GitHunt
AR

armandoblanco/tutorial-copilot-azure-containerapp-auth

Tutorial: Deploy containerized web apps to Azure Container Apps with Microsoft Entra ID authentication using GitHub Copilot Agent Mode

Deploy Web Apps to Azure Container Apps with Entra ID Authentication

A step-by-step tutorial for deploying containerized web applications to Azure using GitHub Copilot in Agent Mode.

๐Ÿ“‹ Overview

This tutorial demonstrates how to leverage GitHub Copilot in Agent Mode to dramatically accelerate your Azure deployment workflow. Instead of manually researching Azure CLI commands, writing scripts, and troubleshooting configurations, you'll use natural language prompts to let Copilot handle the heavy lifting.

What is Agent Mode?
Agent Mode is GitHub Copilot's conversational AI assistant that can execute multi-step tasks, run terminal commands, create files, and interact with Azure directly through the CLI. You simply describe your goal in plain English, and Copilot orchestrates the entire deployment process.

What you'll accomplish:

  • Deploy containerized applications to Azure without writing deployment scripts
  • Configure enterprise-grade authentication using Microsoft Entra ID
  • Test and validate your infrastructure using Azure CLI
  • Learn repeatable patterns for future deployments

Technologies used:

  • Azure Container Registry (ACR) - Store your Docker images
  • Azure Container Apps - Serverless container hosting
  • Microsoft Entra ID - Enterprise authentication
  • Azure CLI - Direct cloud resource management

Why this approach?
Traditional deployment methods require deep knowledge of Azure CLI syntax, infrastructure-as-code tools, and authentication protocols. With GitHub Copilot Agent Mode, you can focus on what you want to achieve while Copilot handles how to implement it, dramatically reducing deployment time from hours to minutes.

๐Ÿ—๏ธ Architecture

graph TB
    User[User Browser] -->|HTTPS| ContainerApp[Azure Container App]
    ContainerApp -->|Authentication| EntraID[Microsoft Entra ID]
    EntraID -->|Token Validation| ContainerApp
    ContainerApp -->|Pull Image| ACR[Azure Container Registry]
    
    Dev[Developer] -->|Build & Push| ACR
    Dev -->|Deploy| ContainerApp
    
    style ContainerApp fill:#0078d4,color:#fff
    style ACR fill:#0078d4,color:#fff
    style EntraID fill:#0078d4,color:#fff
Loading

๐Ÿ”„ Deployment Flow

sequenceDiagram
    participant Dev as Developer
    participant Copilot as GitHub Copilot
    participant ACR as Container Registry
    participant ACA as Container App
    participant EntraID as Entra ID
    
    Dev->>Copilot: "Create Dockerfile for my app"
    Copilot->>Dev: Generates Dockerfile
    Dev->>Copilot: "Deploy to Azure Container Apps"
    Copilot->>ACR: Build & Push image
    Copilot->>ACA: Create/Update Container App
    Dev->>Copilot: "Enable Entra ID authentication"
    Copilot->>EntraID: Register application
    Copilot->>ACA: Configure authentication
    ACA->>Dev: Returns application URL
Loading

โœ… Prerequisites

Before starting, ensure you have:

  • An existing web application (any language/framework)
  • Azure subscription with active access
  • Azure CLI installed
  • GitHub Copilot enabled in VS Code
  • Docker knowledge (basic understanding)

๐Ÿš€ Step-by-Step Guide

Note: All prompts should be used in GitHub Copilot Agent Mode (accessed via the Chat panel in VS Code). Agent Mode allows Copilot to execute multi-step operations, run CLI commands, and manage files automatically.

Step 1: Prepare Your Application

Copilot Prompt:

Create a Dockerfile for my [Python/Node.js/Java/.NET] application that runs on port [PORT_NUMBER]. 
The app requires [list specific dependencies like Flask, Express, Spring Boot, etc.]. 
Also create a .dockerignore file to exclude unnecessary files from the build.

What Copilot will create:

  • Dockerfile - Container build instructions
  • .dockerignore - Files to exclude from the image

Example result:

FROM python:3.11-slim
WORKDIR /app
COPY src/app.py .
EXPOSE 8000
CMD ["python", "app.py"]

Step 2: Deploy Azure Infrastructure

Copilot Prompt:

Use Azure CLI without generating additional files. Create an Azure Resource Group in [region] 
called [myapp-rg]. Then create a Container Registry called [myappregistry]. Build my Docker 
image using ACR build and push it to the registry. Create a Container App Environment and 
deploy a Container App called [myapp-container] with external ingress on port [PORT_NUMBER]. 
Provide me with the final application URL.

What Copilot will do:

  1. Execute Azure CLI commands directly in the terminal
  2. Create Resource Group
  3. Create Azure Container Registry
  4. Build Docker image using ACR
  5. Create Container App Environment
  6. Deploy Container App
  7. Return the application URL

Expected outcome:

โœ… Resource Group: myapp-rg
โœ… Container Registry: myappregistry
โœ… Container App: myapp-container
โœ… URL: https://myapp-container.[random-id].[region].azurecontainerapps.io

Step 3: Enable Entra ID Authentication

Copilot Prompt:

Use Azure CLI to enable Entra ID authentication for my Container App. Register an Entra ID 
application with the appropriate redirect URIs, create a service principal, generate client 
secret, and configure the Container App authentication using Microsoft identity provider. 
Store all configuration values (subscription ID, tenant ID, client ID, client secret, resource 
group, registry name, container app name) in a .env file and update .gitignore to exclude it.

What Copilot will do:

  1. Execute Azure CLI commands to register Entra ID app
  2. Create service principal
  3. Generate client credentials
  4. Configure authentication on Container App using CLI
  5. Create .env file with configuration
  6. Update .gitignore to protect secrets

Configuration stored in .env:

AZURE_SUBSCRIPTION_ID=xxxxx
AZURE_TENANT_ID=xxxxx
ENTRA_CLIENT_ID=xxxxx
ENTRA_CLIENT_SECRET=xxxxx
RESOURCE_GROUP=myapp-rg
REGISTRY_NAME=myappregistry
CONTAINER_APP_NAME=myapp-container

Step 4: Update Your Application Code

Copilot Prompt:

Update my [Python/Node.js/Java/.NET] application to read the X-MS-CLIENT-PRINCIPAL header 
that Azure Container Apps injects after Entra ID authentication. Parse the base64-encoded 
JSON data to extract user claims and display the user's name, email, and authentication 
status on the web page.

What Copilot will add:

For Python applications:

def get_user_info(self):
    auth_header = self.headers.get('X-MS-CLIENT-PRINCIPAL')
    if auth_header:
        user_data = json.loads(base64.b64decode(auth_header))
        return user_data.get('claims', [])
    return None

For Node.js applications:

const authHeader = req.headers['x-ms-client-principal'];
const userData = authHeader ? 
    JSON.parse(Buffer.from(authHeader, 'base64').toString()) : null;

๐Ÿ”ง Manual Alternative: Entra ID Registration

If you prefer to register the Entra ID application manually using Azure CLI commands instead of the prompt-based approach in Step 3, follow these steps:

Note: This is optional. If you already used the Copilot prompt in Step 3, you can skip this section.

1. Register the Application

# Get your Container App URL
APP_URL=$(az containerapp show \
    --name myapp-container \
    --resource-group myapp-rg \
    --query properties.configuration.ingress.fqdn -o tsv)

# Create app registration
APP_ID=$(az ad app create \
    --display-name "MyApp Authentication" \
    --web-redirect-uris "https://$APP_URL/.auth/login/aad/callback" \
    --query appId -o tsv)

echo "Client ID: $APP_ID"

2. Create Service Principal

az ad sp create --id $APP_ID

3. Generate Client Secret

CLIENT_SECRET=$(az ad app credential reset \
    --id $APP_ID \
    --query password -o tsv)

echo "Client Secret: $CLIENT_SECRET"

4. Get Tenant ID

TENANT_ID=$(az account show --query tenantId -o tsv)
echo "Tenant ID: $TENANT_ID"

5. Configure Container App Authentication

# Store client secret
az containerapp secret set \
    --name myapp-container \
    --resource-group myapp-rg \
    --secrets entra-secret=$CLIENT_SECRET

# Configure authentication
az containerapp auth microsoft update \
    --name myapp-container \
    --resource-group myapp-rg \
    --client-id $APP_ID \
    --client-secret-name entra-secret \
    --issuer https://login.microsoftonline.com/$TENANT_ID/v2.0 \
    --allowed-audiences api://$APP_ID \
    --yes

# Require authentication
az containerapp auth update \
    --name myapp-container \
    --resource-group myapp-rg \
    --unauthenticated-client-action RedirectToLoginPage

๐Ÿงช Testing Your Deployment

1. Verify Container App is Running

Copilot Prompt:

Use Azure CLI to check the status of my Container App and show me the current revisions 
with their traffic distribution.

Manual command:

az containerapp revision list \
    --name myapp-container \
    --resource-group myapp-rg \
    --query "[].{Name:name, Active:active, Traffic:trafficWeight}" \
    -o table

2. Test Authentication

Visit your application URL in a browser:

https://myapp-container.[random].[region].azurecontainerapps.io

Expected behavior:

  1. Redirects to Microsoft login page
  2. User authenticates with organizational account
  3. Redirects back to your application
  4. Application displays user information

3. Test API Authentication

# Should return 401 Unauthorized
curl -I https://myapp-container.[url].azurecontainerapps.io

# With valid token, should return 200 OK
curl -H "Authorization: Bearer $TOKEN" \
    https://myapp-container.[url].azurecontainerapps.io

๐Ÿ”„ Continuous Deployment (Optional)

This section is optional but recommended for production deployments.

Option 1: Using GitHub Copilot

Copilot Prompt:

Create a GitHub Actions workflow file that automatically builds and deploys my container app 
to Azure whenever I push to the main branch. Use Azure CLI commands and store Azure credentials 
as GitHub secrets.

Option 2: Manual Deployment Commands

When you need to redeploy after making changes, run these commands directly:

# Load environment variables
source .env

# Set a new version tag
VERSION=$(date +%Y%m%d-%H%M%S)

# Build and push new image version
az acr build \
    --registry $REGISTRY_NAME \
    --image myapp:$VERSION .

# Update Container App with new image
az containerapp update \
    --name $CONTAINER_APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --image $REGISTRY_NAME.azurecr.io/myapp:$VERSION

echo "Deployed version: $VERSION"

๐Ÿ“Š Monitoring and Logs

Copilot Prompt:

Use Azure CLI to show me the real-time logs from my Container App with the --follow flag.

Manual commands:

# View recent logs
az containerapp logs show \
    --name myapp-container \
    --resource-group myapp-rg \
    --follow

# View specific revision logs
az containerapp revision list \
    --name myapp-container \
    --resource-group myapp-rg

๐Ÿ› Troubleshooting

Authentication Not Working

Issue: Users not being redirected to login

Solution:

# Verify auth configuration
az containerapp auth show \
    --name myapp-container \
    --resource-group myapp-rg

Container Not Starting

Issue: Container app shows unhealthy status

Check logs:

az containerapp logs show \
    --name myapp-container \
    --resource-group myapp-rg \
    --tail 50

Common causes:

  • Wrong port configuration (check ingress port matches app port)
  • Missing environment variables
  • Image build errors

Image Pull Errors

Issue: Cannot pull image from registry

Solution:

# Verify registry access
az acr login --name myappregistry

# Check if image exists
az acr repository list --name myappregistry

๐Ÿงน Cleanup Resources

When you're done testing:

Copilot Prompt:

Use Azure CLI to delete the entire Resource Group [myapp-rg] to clean up all resources 
and avoid charges.

Manual command:

az group delete --name myapp-rg --yes --no-wait

๐Ÿ“š Key Concepts Summary

Component Purpose Cost Model
Container Registry Store Docker images Pay per GB stored + data transfer
Container Apps Run containers serverless Pay per vCPU/memory second
Entra ID Enterprise authentication Free for basic features

๐ŸŽฏ Best Practices

  1. Security

    • Always use .gitignore for .env files
    • Store secrets in Azure Key Vault for production
    • Use managed identities when possible
  2. Performance

    • Use minimal base images (alpine, slim variants)
    • Implement health checks
    • Configure appropriate scaling rules
  3. Cost Optimization

    • Scale to zero when not in use
    • Use spot instances for dev/test
    • Monitor actual usage vs. provisioned resources
  4. DevOps

    • Version your container images
    • Implement blue-green deployments
    • Use revision traffic splitting for gradual rollouts

๐Ÿ”— Additional Resources


๐Ÿ’ก Example: Complete Session with Copilot

Here's what a typical deployment conversation looks like:

You: "Create a Dockerfile for my Python web app that runs on port 8000. It uses Flask. 
      Also create a .dockerignore file."
Copilot: [Creates Dockerfile and .dockerignore]

You: "Use Azure CLI to create a Resource Group in East US 2, create a Container Registry,
      build my image, create a Container App, and give me the URL."
Copilot: [Executes all Azure CLI commands, provides URL]

You: "Use Azure CLI to enable Entra ID authentication and save config to .env file."
Copilot: [Registers Entra ID app, configures authentication, creates .env]

You: "Update my Python app to read authentication headers and display user information."
Copilot: [Modifies app code to parse X-MS-CLIENT-PRINCIPAL header]

You: "Use Azure CLI to rebuild and redeploy my container with the latest changes."
Copilot: [Builds new image version, updates Container App]

That's it! You now have a fully deployed, authenticated web application on Azure.


Last Updated: February 2026
Difficulty Level: Intermediate
Estimated Time: 30-45 minutes
Use Azure CLI to rebuild and redeploy my container with the latest changes"
Copilot: [Builds new image version, updates Container App