4. Deploy Containers to Azure Container Apps

๐Ÿ“š Learning Objectives

After completing this exercise, you will be able to:

๐Ÿ”ง Prerequisites

๐Ÿ“‹ What is Azure Container Apps?

Azure Container Apps is a serverless container hosting service that allows you to:

Think of it as: “Just give Azure your container, and it handles everything else”

๐ŸŽฏ Part A: Deploy via Azure Portal

Step 1: Create Container Apps Environment

  1. Navigate to Azure Portal

  2. Click “Create a resource” โ†’ Search for “Container App”

  3. Click “Create” on the Container App page

  4. Basics tab:

    • Subscription: Select your subscription
    • Resource group: Create new โ†’ container-apps-demo-rg
    • Container app name: php-demo-app
    • Region: North Europe (or your preferred region)
    • Container Apps Environment: Create new
  5. Container Apps Environment:

    • Environment name: container-apps-env
    • Zone redundancy: Disabled (for demo)
    • Click OK

Step 2: Configure Container

  1. Container tab:
    • Image source: Docker Hub or other registries
    • Image type: Public
    • Registry login server: docker.io
    • Image and tag: nginx:alpine (we’ll start with nginx)
    • CPU and Memory: 0.25 CPU cores, 0.5 Gi memory

Step 3: Configure Ingress

  1. Ingress tab:

    • Ingress: Enabled
    • Ingress traffic: Accepting traffic from anywhere
    • Ingress type: HTTP
    • Target port: 80
  2. Click “Review + create” โ†’ “Create”

  3. Wait for deployment (typically 2-3 minutes)

Step 4: Test the Deployment

  1. Go to your Container App resource
  2. Click on “Application Url” in the Overview
  3. You should see the nginx welcome page

Step 5: Update to Your PHP Application

  1. In your Container App, go to “Containers” โ†’ “Edit and deploy”

  2. Update the image:

    • Image and tag: yourusername/php-simple-app:latest
    • Target port: Keep as 80 (or 8000 if using PHP built-in server)
  3. Click “Save” โ†’ “Create”

  4. Wait for the new revision to deploy

  5. Refresh your application URL - you should see your PHP app!

๐ŸŽฏ Part B: Deploy via Azure CLI

Step 1: Run the Provisioning Script

Create a script that automates the entire process:

provision-container-app.sh

#!/bin/bash

# Azure Container Apps Provisioning Script
# This script deploys a container to Azure Container Apps
# First with nginx, then updates to a custom PHP application

# Configuration variables
RESOURCE_GROUP="container-apps-demo-rg"
LOCATION="northeurope"
ENVIRONMENT="container-apps-env"
APP_NAME="php-demo-app"

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Function to print colored output
print_status() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

# Check if Azure CLI is installed
if ! command -v az &> /dev/null; then
    print_error "Azure CLI is not installed. Please install it first."
    echo "Visit: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli"
    exit 1
fi

print_status "Starting Azure Container Apps deployment..."

# Step 1: Create Resource Group
print_status "Creating Resource Group: $RESOURCE_GROUP"
az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION \
    --output none

if [ $? -eq 0 ]; then
    print_status "Resource Group created successfully"
else
    print_error "Failed to create Resource Group"
    exit 1
fi

# Step 2: Create Container Apps Environment
print_status "Creating Container Apps Environment: $ENVIRONMENT"
az containerapp env create \
    --name $ENVIRONMENT \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --output none

if [ $? -eq 0 ]; then
    print_status "Container Apps Environment created successfully"
else
    print_error "Failed to create Container Apps Environment"
    exit 1
fi

# Step 3: Deploy nginx container first
print_status "Deploying nginx container to test the setup..."
NGINX_URL=$(az containerapp create \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --environment $ENVIRONMENT \
    --image nginx:alpine \
    --target-port 80 \
    --ingress external \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

if [ $? -eq 0 ]; then
    print_status "nginx container deployed successfully"
    print_status "Application URL: https://$NGINX_URL"
    echo ""
    print_warning "Please test the nginx deployment at: https://$NGINX_URL"
    echo ""
else
    print_error "Failed to deploy nginx container"
    exit 1
fi

# Step 4: Ask user if they want to update to PHP app
read -p "Do you want to update to your PHP application? (y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
    # Get Docker Hub username
    read -p "Enter your Docker Hub username: " DOCKER_USERNAME
    
    # Update to PHP application
    print_status "Updating to PHP application..."
    PHP_URL=$(az containerapp update \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --image $DOCKER_USERNAME/php-simple-app:latest \
        --query properties.configuration.ingress.fqdn \
        --output tsv)
    
    if [ $? -eq 0 ]; then
        print_status "PHP application deployed successfully"
        print_status "Application URL: https://$PHP_URL"
    else
        print_error "Failed to update to PHP application"
        print_warning "Container might not exist on Docker Hub. Please push it first:"
        echo "  docker push $DOCKER_USERNAME/php-simple-app:latest"
    fi
fi

# Step 5: Display summary
echo ""
echo "========================================="
echo "Deployment Summary"
echo "========================================="
echo "Resource Group: $RESOURCE_GROUP"
echo "Location: $LOCATION"
echo "Environment: $ENVIRONMENT"
echo "App Name: $APP_NAME"
echo "App URL: https://$NGINX_URL"
echo "========================================="

# Step 6: Cleanup option
echo ""
read -p "Do you want to delete all resources? (y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
    print_warning "Deleting all resources..."
    az group delete \
        --name $RESOURCE_GROUP \
        --yes \
        --no-wait
    print_status "Resource deletion initiated (running in background)"
else
    print_status "Resources kept. To delete later, run:"
    echo "  az group delete --name $RESOURCE_GROUP --yes"
fi

print_status "Script completed!"
# Make it executable
chmod +x provision-container-app.sh

# Run the script
./provision-container-app.sh

Step 2: Manual CLI Commands

If you prefer to run commands individually:

# Set variables
RESOURCE_GROUP="container-apps-demo-rg"
LOCATION="northeurope"
ENVIRONMENT="container-apps-env"
APP_NAME="php-demo-app"

# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

# Create environment
az containerapp env create \
    --name $ENVIRONMENT \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION

# Deploy nginx first
az containerapp create \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --environment $ENVIRONMENT \
    --image nginx:alpine \
    --target-port 80 \
    --ingress external

# Get the URL
az containerapp show \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --query properties.configuration.ingress.fqdn \
    --output tsv

# Update to your PHP app
az containerapp update \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --image yourusername/php-simple-app:latest

๐Ÿ” Viewing Logs and Monitoring

Via Portal:

  1. Go to your Container App
  2. Click “Log stream” to see real-time logs
  3. Click “Metrics” to view performance data

Via CLI:

# View logs
az containerapp logs show \
    --name php-demo-app \
    --resource-group container-apps-demo-rg \
    --follow

# View recent logs
az containerapp logs show \
    --name php-demo-app \
    --resource-group container-apps-demo-rg \
    --tail 100

๐ŸŽฏ Testing Your Application

  1. Get the application URL:
az containerapp show \
    --name php-demo-app \
    --resource-group container-apps-demo-rg \
    --query properties.configuration.ingress.fqdn \
    --output tsv
  1. Test with curl:
APP_URL=$(az containerapp show -n php-demo-app -g container-apps-demo-rg --query properties.configuration.ingress.fqdn -o tsv)
curl https://$APP_URL
  1. Open in browser:
    • Navigate to the URL provided
    • Test your PHP contact form

๐Ÿ’ฐ Cost Considerations

Azure Container Apps pricing:

For our demo app (0.25 vCPU):

๐Ÿงน Cleanup

To avoid charges, delete all resources:

Via Portal:

  1. Go to Resource Groups
  2. Select container-apps-demo-rg
  3. Click “Delete resource group”
  4. Type the resource group name to confirm
  5. Click “Delete”

Via CLI:

# Delete everything
az group delete --name container-apps-demo-rg --yes --no-wait

๐Ÿ“ Troubleshooting

Container fails to start

Application not accessible

Image pull errors

# For private registries, configure credentials
az containerapp registry set \
    --name php-demo-app \
    --resource-group container-apps-demo-rg \
    --server docker.io \
    --username your-docker-username \
    --password your-docker-password

๐ŸŽ‰ Summary

You’ve successfully:

Key Benefits of Container Apps:

๐Ÿš€ Next Steps

๐Ÿ“š Additional Resources