This repository demonstrates how to containerize the Record Store Application and deploy it to Azure using serverless container hosting services.
The application is first upgraded to ASP.NET Core using Visual Studio 2022 to enable easy containerization in a Linux environment.
The application is containerized using Visual Studio Container Tools or Docker Desktop.
The following Dockerfile is used:
FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:35792ea4ad1db051981f62b313f1be3b46b1f45cadbaa3c288cd0d3056eefb83 AS build
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0@sha256:6c4df091e4e531bb93bdbfe7e7f0998e7ced344f54426b7e874116a3dc3233ff
WORKDIR /App
COPY --from=build /App/out .
# Replace with project's dll file
ENTRYPOINT ["dotnet", "WebApplication8Core.dll"]A docker image named record-store-app is built using the following command:
docker build -t record-store-app .To test the application, a local container can be created:
sudo docker run -p 8080:8080 -it --rm record-store-appThe application is accessible at http://localhost:8080.
The image is pushed to Github Container Registry to be publicly available.
- Authenticating to the registry:
export CR_PAT=<PAT> # PAT must include write:packages permission
echo $CR_PAT | docker login ghcr.io -u <USERNAME> --password-stdin- Tagging and pushing the image:
docker tag record-store-app ghcr.io/<USERNAME>/record-store-app:1.0.0
docker push ghcr.io/<USERNAME>/record-store-app:1.0.0- The image can be pulled using:
docker pull ghcr.io/USERNAME/record-store-app:1.0.0
Also available at Github Packages.
For deployment, the architecture from the private_app_on_azure repository can be used. An App Service can consume a container by setting the linuxFxVersion property:
resource app_service 'Microsoft.Web/sites@2023-12-01' = {
name: name
location: location
properties: {
serverFarmId: asp_id
siteConfig: {
linuxFxVersion: 'DOCKER|ghcr.io/<USERNAME>/record-store-app:1.0.0'
}
}
}Alternatively, Azure provides multiple container-based hosting solutions. For simplicity, the architecture in this repository uses:
Container Registry (acrrecordstore7pat): To store the container imageContainer Instances (ci-record-store): For lightweight deploymentUser-assigned Managed Identity (id-ci-record-store): For authorizing the Container Instance to pull images from the Container Registry
To secure the image access, a private Azure Container Registry (ACR) is used with a private endpoint and a private DNS zone privatelink.azurecr.io.
Azure Container Instances operate within a delegated subnet and are accessed through private IPs only.
The GitHub Runner functions as a jump host to interact with the private network.
A Linux virtual machine is configured as a GitHub self-hosted runner using a bash script. It installs:
- Azure CLI
- Docker
The runner pulls the image from GitHub, tags it and pushes it to the private ACR. The service principal used for this task requires AcrPush permissions.
In this architecture, App Service, App service Plan and Application Insights are removed.
The Container Instance pulls the image from the private ACR using a user-assigned managed identity with AcrPull permissions.
To test the deployment, the GitHub Runner can be used as a jump host to connect into the private network and curl the private IP address of the container instance.
Monitoring
Logs and basic container insights are available in Log Analytics Workspace resource under ContainerEvent_CL table:
Several workflows automate the deployment process. These are similar to those found in the private_app_on_azure repository:
Deploy Infrastructure: Creates the necessary Azure resources (excluding the container).
Push Image to ACR: Tags and pushes the Docker image to ACR, using the Github Runner.Deploy Container: Deploys the container to Azure after the image is available.Import Data to Database: Importing data into the SQL database.
- Container Instances are ephemeral and not ideal for long-running production workloads.
- Azure Container Instances do not support autoscaling.
- ACI applications require additional infastructure to be safely exposed to the internet.
app_on_azure_kubernetes: Deploying and exposing the Record Store application on Azure Kubernetes Service (AKS).

