Deploying Container Apps
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Lesson: Deploying Container Apps in Microsoft Azure
Introduction: The Modern Shift to Containerized Workloads
In the landscape of modern software development, the way we package, ship, and run applications has undergone a significant transformation. Gone are the days when developers had to worry about the underlying operating system configurations, dependency conflicts, or the "it works on my machine" syndrome. Containers have emerged as the standard solution for these challenges, providing a consistent, lightweight, and portable environment for code. By bundling an application with its dependencies, libraries, and configuration files, containers ensure that software behaves exactly the same way in development, testing, and production.
Azure Container Apps (ACA) represents the next evolution in this journey. It is a serverless container platform that allows you to run microservices and containerized applications without the overhead of managing complex infrastructure like Kubernetes clusters. While Azure offers other services like Azure Kubernetes Service (AKS) for granular control, Azure Container Apps is designed for developers who want to focus on building features rather than managing virtual machines, networking, or orchestration nodes.
Understanding how to deploy and manage container apps is critical for any cloud engineer or developer working in the Azure ecosystem. Whether you are migrating a legacy application or building a greenfield microservices architecture, mastering container deployment will significantly improve your team's velocity and the reliability of your production environment. In this lesson, we will explore the mechanics of Azure Container Apps, learn how to configure them, and discuss the best practices for maintaining them in a production setting.
Understanding the Architecture of Azure Container Apps
Before we dive into the deployment process, it is important to understand the fundamental building blocks of Azure Container Apps. Unlike a standard virtual machine that runs a single OS instance, Azure Container Apps operates on the concept of "Environments" and "Apps."
The Container Apps Environment
Think of the Environment as a secure boundary that groups your containerized applications together. Within this boundary, all apps share the same virtual network and logging configuration. This is where the magic of internal service discovery happens. When you deploy multiple microservices into the same environment, they can talk to each other using simple Dapr-enabled service-to-service communication or standard HTTP calls, without needing to expose those endpoints to the public internet.
Revisions, Scales, and Traffic
At the heart of an individual Container App are three core concepts:
- Revisions: A revision is an immutable snapshot of your container app. Every time you change the configuration or the container image, Azure creates a new revision. This allows you to perform blue-green deployments or canary releases by shifting traffic between different versions of your code.
- Scaling: Azure Container Apps can scale based on HTTP traffic, event-driven triggers (like a message in a queue), or even CPU/Memory usage. You can define minimum and maximum replica counts, allowing the system to scale down to zero when no traffic is present to save costs.
- Traffic Splitting: You can define rules to split incoming traffic across multiple revisions. This is useful for testing new versions with a small subset of users before rolling the update out to the entire population.
Callout: Azure Container Apps vs. AKS It is common to wonder when to choose Azure Container Apps versus Azure Kubernetes Service (AKS). Use Azure Container Apps when you want a serverless experience where Azure manages the underlying cluster, scaling, and platform updates. Choose AKS when you require deep control over the Kubernetes control plane, need to install custom Kubernetes operators, or have highly specific networking requirements that the managed environment cannot satisfy.
Preparing for Deployment
Before deploying your first app, you must have your environment properly configured. This involves setting up the Azure CLI, creating a resource group, and establishing a Container Apps Environment.
Prerequisites
- An active Azure subscription.
- The Azure CLI installed on your local machine.
- A container image stored in a registry (like Azure Container Registry or Docker Hub).
Step-by-Step: Setting Up the Environment
First, ensure you are logged into your Azure account and have selected the correct subscription. Next, create a resource group to contain all your related resources.
# Log in to Azure
az login
# Set your subscription
az account set --subscription "Your-Subscription-ID"
# Create a resource group
az group create --name my-container-rg --location eastus
Once the resource group is created, you need to create the Log Analytics workspace. Azure Container Apps requires this to store logs and metrics, which are essential for troubleshooting and monitoring.
# Create a Log Analytics workspace
az monitor log-analytics workspace create \
--resource-group my-container-rg \
--workspace-name my-container-logs \
--location eastus
Finally, create the Container Apps Environment. This acts as the container for your applications.
# Get the workspace ID
LOG_ANALYTICS_ID=$(az monitor log-analytics workspace show \
--resource-group my-container-rg \
--workspace-name my-container-logs \
--query id --output tsv)
# Create the environment
az containerapp env create \
--name my-environment \
--resource-group my-container-rg \
--location eastus \
--logs-workspace-id $LOG_ANALYTICS_ID \
--logs-workspace-key $(az monitor log-analytics workspace get-shared-keys \
--resource-group my-container-rg \
--workspace-name my-container-logs \
--query primarySharedKey --output tsv)
Note: Always place your Log Analytics workspace in the same region as your Container Apps environment to minimize latency and avoid potential data egress costs.
Deploying Your First Container App
Now that the infrastructure is ready, we can deploy an application. We will use a simple "Hello World" container image for this demonstration.
The Deployment Command
The az containerapp create command is the primary way to deploy an app. You need to specify the environment, the image, and whether the app should be accessible from the public internet.
az containerapp create \
--name my-hello-app \
--resource-group my-container-rg \
--environment my-environment \
--image mcr.microsoft.com/azuredocs/containerapps-helloworld:latest \
--target-port 80 \
--ingress external \
--query properties.configuration.ingress.fqdn
Explaining the Parameters:
--name: The unique name for your specific application.--image: The path to your container image. This can point to Docker Hub, Azure Container Registry (ACR), or any other private registry.--target-port: The port that your application listens on inside the container.--ingress external: This makes your app reachable from the internet. If you are building a backend service that should only be accessible internally, use--ingress internalinstead.--query: This is a helpful CLI feature that outputs the Fully Qualified Domain Name (FQDN) of your new application immediately upon completion.
Verification
Once the command finishes, copy the FQDN provided in the output and paste it into your web browser. You should see the default landing page for the container app. If you don't see it immediately, wait about 30 seconds for the container to pull the image and start the application.
Advanced Configuration: Environment Variables and Secrets
In real-world scenarios, your application will rarely run in isolation. It will likely need to connect to a database, an API, or a cache. Hardcoding these connection strings into your container image is a major security risk. Instead, use Environment Variables and Azure Key Vault secrets.
Injecting Environment Variables
You can pass configuration settings to your container during deployment or update them later using the CLI.
az containerapp update \
--name my-hello-app \
--resource-group my-container-rg \
--set-env-vars "APP_COLOR=blue" "DB_CONNECTION=server=tcp:mydb.database.windows.net"
Managing Secrets
For sensitive information like passwords or API keys, use the built-in secret management. You can define secrets in the app configuration and then reference them in your environment variables.
# Add a secret to the app
az containerapp secret set \
--name my-hello-app \
--resource-group my-container-rg \
--secrets "db-password=my-super-secret-password"
# Use the secret in an environment variable
az containerapp update \
--name my-hello-app \
--resource-group my-container-rg \
--set-env-vars "DB_PASSWORD=secretref:db-password"
Warning: Never store credentials in plaintext inside your source code or Dockerfiles. Always use environment variables or a dedicated secret store like Azure Key Vault. Even if your image is private, it is a bad habit that can lead to security breaches if the image is ever leaked or shared.
Scaling and Traffic Management
One of the primary benefits of Azure Container Apps is its ability to handle fluctuating traffic loads. Because it is built on KEDA (Kubernetes Event-driven Autoscaling), you have immense flexibility in how you define scaling rules.
Configuring Scaling Rules
You can scale based on HTTP requests, or you can scale based on external triggers like Azure Service Bus queues, Kafka topics, or Redis streams.
# Scale based on HTTP requests
az containerapp update \
--name my-hello-app \
--resource-group my-container-rg \
--min-replicas 1 \
--max-replicas 10 \
--scale-rule-name http-rule \
--scale-rule-type http \
--scale-rule-http-concurrency 50
This configuration tells Azure: "Start with at least one instance, but if the number of concurrent requests exceeds 50 per instance, spin up more instances, up to a maximum of 10."
Blue/Green Deployments
When you update your application, you can control how traffic is routed. This allows you to deploy a new version (a new revision) and send only 10% of your traffic to it, keeping 90% on the stable version.
# Update the image for a new revision
az containerapp update \
--name my-hello-app \
--resource-group my-container-rg \
--image my-registry.azurecr.io/myapp:v2
# Split traffic between revisions
az containerapp ingress traffic set \
--name my-hello-app \
--resource-group my-container-rg \
--traffic-weights "latest=90" "my-hello-app--v1=10"
This is a powerful technique for reducing the impact of bugs. If the new version (the "latest" revision) shows errors in your logs, you can instantly revert traffic to the stable v1 revision.
Best Practices for Production
Deploying to production requires more than just getting the container to run. You must consider security, observability, and lifecycle management.
Container Security
- Use Distroless or Slim Images: Minimize the attack surface of your container by removing shells, package managers, and other unnecessary tools.
- Run as Non-Root: Configure your Dockerfile to run the application as a non-privileged user. This prevents an attacker who gains control of the container from having root access to the container filesystem.
- Scan for Vulnerabilities: Use tools like Microsoft Defender for Containers to scan your images for known vulnerabilities before deploying them to your registry.
Observability
- Centralized Logging: Always ensure your logs are being sent to your Log Analytics workspace. Use KQL (Kusto Query Language) to query these logs to identify errors or performance bottlenecks.
- Distributed Tracing: If you have multiple microservices, consider implementing OpenTelemetry or Dapr to track requests as they move across service boundaries.
- Health Probes: Always define liveness and readiness probes. If your app crashes, the liveness probe tells Azure to restart the container. If your app is still starting up, the readiness probe ensures no traffic is sent to it until it is truly ready.
Networking
- Private Endpoints: For mission-critical applications, disable public ingress and use Azure Private Link to expose your application only within your virtual network.
- VNet Integration: If your container app needs to talk to a database inside a private virtual network, you must configure VNet integration for your Container Apps Environment.
Common Pitfalls and Troubleshooting
Even with a managed platform, things can go wrong. Here are the most common issues developers encounter and how to fix them.
1. "Image Pull Backoff"
This error usually means Azure cannot download your container image.
- Check Registry Access: If using a private Azure Container Registry, ensure your Container App has an identity with the "AcrPull" role assigned.
- Check Image Tags: Ensure the tag you specified actually exists in your registry.
2. Application Crashing on Startup
If your app container starts and immediately exits, check the logs.
- Use the CLI:
az containerapp logs show --name my-app --resource-group my-rg - Check Environment Variables: Often, the app crashes because it is missing a required environment variable or cannot connect to a database due to a bad connection string.
3. Scaling Issues
If your app is not scaling as expected:
- Check the Metric: Look at your metrics in the Azure Portal. Are you hitting the trigger threshold?
- Review Quotas: Ensure you haven't hit the subscription limit for the number of CPUs or memory allowed in your region.
Callout: The Importance of Idempotency When working with containers, assume that any instance can be destroyed or replaced at any time. Your application must be stateless. Do not store user sessions or temporary files on the local container disk. If you need state, use an external store like Azure Cache for Redis or a database like Azure Cosmos DB. This ensures that when your app scales or a node is updated, no data is lost and the user experience remains consistent.
Comparison Table: Deployment Strategies
| Strategy | Description | Best For |
|---|---|---|
| Direct Deployment | Overwriting the current revision. | Rapid development and testing. |
| Blue/Green | Deploying a new version and shifting all traffic. | Production updates with minimal risk. |
| Canary | Shifting a small percentage of traffic to a new version. | Validating new features with real users. |
| A/B Testing | Routing traffic based on user attributes or headers. | Experimenting with different UX/features. |
Summary and Key Takeaways
Deploying container apps in Azure is a powerful way to manage modern applications without the complexity of traditional cluster management. By focusing on the concepts of environments, revisions, and scaling rules, you can create highly resilient systems that adapt to user demand.
Key Takeaways:
- Environment Isolation: Always group related microservices into the same Container Apps Environment to enable efficient service discovery and shared infrastructure.
- Immutability: Treat every revision as an immutable object. When you need to change your app, deploy a new revision rather than modifying a running one.
- Security First: Never hardcode secrets. Use the built-in secret management and always run your containers with the least privilege necessary.
- Scaling is Configurable: Leverage KEDA to scale your applications based on real-world events, not just CPU or memory, to ensure cost efficiency.
- Observability is Mandatory: Without logging and monitoring, you are flying blind. Ensure your Log Analytics workspace is configured correctly from day one.
- Use Traffic Splitting: Always use revisions and traffic splitting for production updates. It is the single best way to prevent a bad deployment from causing an outage.
- Statelessness: Design your containers to be stateless. This is the fundamental requirement for successful scaling and high availability in any containerized environment.
By following these principles and utilizing the tools provided by the Azure CLI and the platform itself, you can build, deploy, and manage containerized applications with confidence and efficiency. Remember that technology evolves; always keep an eye on the official Azure documentation for new features and updates to the Container Apps platform.
Frequently Asked Questions (FAQ)
Can I run multiple containers in a single Container App?
Yes, you can use "sidecars." This is useful for running a logging agent, a proxy, or a helper process alongside your main application container. All containers in a single app share the same network and storage.
Does Azure Container Apps support persistent storage?
Yes, you can mount Azure Files as a volume to your container app. This is useful for scenarios where you need to share files between replicas or persist data that cannot be stored in a database.
How do I handle custom domains?
You can map a custom domain to your Container App by configuring a CNAME record with your DNS provider and adding the domain in the Azure Portal or via CLI under the "Custom domains" section of your app settings. You will also need to manage an SSL certificate, which can be done automatically via managed certificates in Azure.
Is there a cost for idle applications?
Azure Container Apps offers a "consumption plan" where you are only charged for the resources your application uses while it is running. If your app scales to zero, you stop paying for compute, though you may still pay a small amount for the environment infrastructure and logging storage.
Can I use GitHub Actions to deploy my apps?
Absolutely. Azure provides a GitHub Action specifically for Container Apps that simplifies the process of building your image and deploying it to your environment automatically whenever you push code to your repository. This is the industry standard for CI/CD pipelines in Azure.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons