This application is a containerized example of a .NET web API that can be deployed to Azure Container Apps, Azure App Service, or AKS. My attempt is to demonstrates best practices for continuous deployment of containers.
This project is based on the sample ToDo .NET web API from the Microsoft Learn site: Create web API using ASP.NET Core. Additional controllers have been added:
- TodoController: Implements CRUD operations using an in-memory database for
TodoItemDTO
objects. - WeatherForecastController: Returns a hardcoded weather forecast for testing purposes.
- ConfigController: Demonstrates Azure App Configuration. Learn more about Azure App Configuration.
The project includes a Dockerfile for containerization and multiple GitHub Actions workflows. See Github Worflows section below for details on each deployment type.
Workflow Name | Badge |
---|---|
Azure Container App Deployment | |
Azure App Service Deployment | |
Azure App Service Slot Deployment | |
Azure Kubernetes Service (AKS) Deployment |
This repository is designed to be cloned and customized. Follow the steps below to set it up.
- Azure Subscription
- GitHub Repository: Clone this repository into your own GitHub account.
- Configuration File: Create an
appsettings.Development.json
file based on the structure inappsettings.json
. - Service Principal: Create a service principal with Contributor access to your Azure subscription. The credentials for this service principle need to be stored according to this document: Service Principal Secret and stored in a GitHub secret named
AZURE_CREDENTIALS
. You will also need to assign theUser Access Administrator
role because we are doing role assignments in the bicep files. - Azure App Configuration Resource (Optional):
-
Add the following configuration settings:
Key Value Label TestAp:Settings:Message DEV - Data from Azure App Configuration dev TestAp:Settings:Message TEST - Data from Azure App Configuration test TestAp:Settings:Sentinel 1 TestAp:<oid for user 1>:Sentinel ConnectionStringForUser1 TestAp:<oid for user 2>:Sentinel ConnectionStringForUser2 -
Replace
<oid for user 1>
and<oid for user 2>
with actual Object IDs. -
Create a managed identity and grant it
App Configuration Data Reader
access.
-
- Clone the repository.
- Update the
env
section in the workflows with your Azure resource names. - Add the
AZURE_CREDENTIALS
secret to your GitHub repository. - (Optional) Configure Azure App Configuration as described above.
This project includes workflows for deploying to Azure Container Apps, App Service, and AKS.
Deploys to Azure Container Apps in four stages:
- build: Builds and tags the container image.
- deploy: Deploys the container image to Azure Container Apps. There is another repo that contains a UI (Blazor client app) that will call this
todo
. There is a reference here to that client UI to get the URI that can be added to CORS. If it doesn't exist it will add*
.
Deploys to AKS in three stages:
- buildInfra: Creates infrastructure using Bicep templates.
- buildImage: Builds and tags the container image.
- deploy: Deploys the container to AKS and updates CORS settings. While this repo is only for the
todo
api, there is another repo that creates a UI (Blazor client app) that connects to this todo api. The first part of this stage is to get that URL so we can add it to the CORS list. Next we use ased
script to replace variables in the AKS deployment file so it can be dynamic to use the container image we just built.
Deploys to Azure App Service in two stages:
- build-infra: Creates infrastructure using Bicep templates.
- build-deploy: Builds, tags, and deploys the container image.
Demonstrates slot deployments for zero downtime. Stages:
- build-deploy: Builds, tags, and deploys the container image.
- swap-slot: Swaps the staging slot with the production slot after manual approval.
Use the monitor-api.sh
script to test slot swapping. It pings the api every 2 seconds to show how the latency isn't impacted by just swapping the slots. If you want, you can create a copy of the monitor-api.sh
file into an environment specific file monitor-api.dev.sh
that is ignored by the .gitignore
file. Here is an example output that shows the response changes from being prefixed with 'green' and then swapped to be prefixed with 'blue':