Deploying SKS Blazor migrated app to Azure Container Instances

This document provides a detailed guide for deploying SKS Blazor migrated applications using Azure Container Instances (ACI). It covers the necessary steps for setting up a local Docker environment, building container images, defining base images, and pushing images to container registries, specifically GitHub Container Registry (GHCR) and Azure Container Registry (ACR). Additionally, it includes instructions for creating and running containers in Azure, along with important considerations for ensuring successful deployment, particularly regarding the choice of base images and runtime dependencies for Windows-based applications.

Installing Docker local environment.

To first build a Docker image with the SKS application is important to install and configure a local Docker runtime environment.

  1. Add containers and hyper-v features on windows:

    1. Open Windows Features:

      1. Press Win + R, type optional features, and press Enter.

      2. Or, search for "Turn Windows features on or off" in the Start menu and open it.

    2. Enable Containers:

      1. In the Windows Features dialog, scroll down and check the box for Containers.

    3. Enable Hyper-V:

      1. In the same list, find and check Hyper-V (expand it and ensure both "Hyper-V Management Tools" and "Hyper-V Platform" are checked).

    4. Apply and Restart:

      1. Click OK.

      2. Windows will search for required files and apply changes.

      3. Restart your computer when prompted.

  2. Run the installer (Docker Desktop Installer.exe)

  3. During installation:

    1. Enable "Install required Windows components for WSL 2"

    2. Enable "Use Windows containers instead of Linux containers"

  4. Click "Ok" to install

  5. Wait for installation to complete

  6. Restart your computer

  7. Run Docker desktop application.

  8. Right click on Docker tray icon and select switch to windows containers (Since the images used to build the WebMap Blazor images are Windows OS based it’s necessary to work with Windows containers).

  9. In settings verify that desktop-windows is running

How to build a Windows image with SKS app.

For this exercise the SKS application was used. You can find the application along with the Dockerfile in the repo: https://collaboration.artinsoft.com/tfs/Product/Product/_git/BlazorDemos

The branch with the changes and the Dockerfile is: support/DockerContainerWindowsSKS.

Before creating the Dockerfile it’s important to define the base image used to create the container.

Defining a base image

There a are 3 different types of base image the election should be based on the requirements:

  • Linux Images

    • Base OS: Linux (usually Debian or Alpine).

    • Size: Smallest.

    • Performance: Fast startup, low resource usage.

    • Compatibility:

      • Runs on Linux hosts (including most cloud/container platforms).

      • Cannot run Windows-specific workloads (e.g., Windows Forms, WPF, COM).

    • Best for:

      • Web apps (Blazor, ASP.NET Core, APIs).

      • Cloud-native deployments (Azure Container Apps, Kubernetes, Docker Hub).

  • Nano Server Images

    • Base OS: Windows Nano Server (minimal Windows kernel).

    • Size: Smaller than Server Core, larger than Linux.

    • Performance: Good, but not as fast or small as Linux.

    • Compatibility:

      • Runs only on Windows hosts (Windows containers).

    • No support for full .NET Framework, Windows Forms, WPF, or GDI+.

    • Only supports .NET Core/.NET 5+ console and web apps.

    • Best for:

      • .NET Core web apps that require Windows but not full Windows APIs.

  • Server Core Images

    • Base OS: Windows Server Core (more complete Windows environment).

    • Size: Largest.

    • Performance: Slower startup, higher resource usage.

    • Compatibility:

      • Runs only on Windows hosts (Windows containers).

      • Supports full .NET Framework, Windows Forms, WPF, GDI+, COM, etc.

    • Best for:

      • Legacy .NET Framework apps.

      • Apps needing full Windows APIs (desktop, GUI, COM, etc.).

Since most migrations come from windows architecture usually they are tightly coupled to windows environments, also WebMap Blazor code is compiled and designed to target Windows Desktop runtime that’s why the selected base image for the SKS POC is Server Core Images.

Once the based image is defined, a Dockerfile should be created to perform the image build. The Dockerfile used for this exercise can be found in the branch mentioned above.

After creating the Dockerfile, open a command line window pointing to the same folder where the dockerfile is and run the build command to generate an image.

docker build --no-cache -t <desired-image-name>:<version>

You should have the image created in the docker desktop UI.

Then you can run the image locally as a container using the docker run command.

docker run -p 8080:8080 -p 8081:8081 --name <desired-container-name> <image-name-used-build-command>

There should be a new container named sks_blazor_container created

Since one of the ports exposed when running the container is 8080. The app will listen in http://localhost:8080

Next step is to push the image to a Container registry so it can be run from the Azure Container instances app. But first you need to define which container registry to use.

Define container registry

These are some of the most common container registry options:

  • Git Hub Container Registry

    • Free for public repositories and generous free tier for private images.

    • No extra Azure cost (unlike ACR, which may incur charges after the free tier).

    • Easy integration with GitHub Actions for CI/CD.

    • Widely supported by Azure Container Apps and Azure Web App for Containers.

    • No vendor lock-in—you can use the same registry for other platforms.

  • Docker Hub

    • Free for public images (rate limits apply).

    • Simple to use and supported everywhere.

    • Private repositories are limited to the free tier.

  • Azure Container Registry

  • Using GHCR to push the image to the remote repository

    • Go to GitHub.com → Settings → Developer Settings → Personal Access Tokens → Tokens (classic).

    • Click "Generate new token (classic)"

    • Select the following scopes:

      • read:packages

      • write:packages

      • delete:packages (if you need to delete containers)

    • Copy the generated token

    • Login the local docker environment to GHCR:

      • echo <GENERATED-TOKEN>| docker login ghcr.io -u <YOUR_GITHUB_USERNAME> --password-stdin
    • Tag the image in GHCR:

      • docker tag <image-name>:<version> ghcr.io/<YOUR_GITHUB_USERNAME>/<image-name>:<version>
    • Push the image

      • docker push ghcr.io/<YOUR_GITHUB_USERNAME>/<image-name>:<version>
  • Using ACR to push the image to the remote repository

    • Open the Azure Portal

      • Go to https://portal.azure.com and sign in with your Azure account.

    • Open Azure Cloud Shell

      • In the top-right corner of the portal, click the Cloud Shell icon (it looks like a terminal or command prompt).

      • When prompted, select Bash as your shell environment.

      • If this is your first time, you may be asked to create a storage account—follow the prompts to set it up.

    • Create a resource group.

    az group create --name <resource-group-name> --location <location>
    • Create ACR

    az acr create --resource-group <resource-group-name> --name <acr-name> --sku Basic
    • Go back to you local environment, open a cmd and login to azure.

    az login
    • Login to acr.

    az acr login --name <acr-name>
    • Tag the image.

    docker tag <image-name>:<version> <acr-name>.azurecr.io/<image-name>:<version>
    • Push the image.

    docker push <acr-name>.azurecr.io/<image-name>:<version>

Create an Azure Container instance that runs the pushed image.

  1. Open the Azure Portal

    1. Go to https://portal.azure.com and sign in with your Azure account.

  2. Open Azure Cloud Shell

    1. In the top-right corner of the portal, click the Cloud Shell icon (it looks like a terminal or command prompt).

    2. When prompted, select Bash as your shell environment.

    3. If this is your first time, you may be asked to create a storage account—follow the prompts to set it up.

  3. Create a resource group (If you don't have one).

az group create --name <resource-group-name> --location <location>
  1. Create Azure Container Instances.

    1. Using GHCR:

    az container create   --resource-group <resource-group-name>   
    --name <aci-name> 
     --image ghcr.io/<YOUR_GITHUB_USERNAME>/<image-name>:<version>   --registry-login-server ghcr.io   
    --registry-username <YOUR_GITHUB_USERNAME>  --registry-password <GENERATED-TOKEN>   
    --dns-name-label <desired-site-name>  --ports 8080 8081 
    --os-type Windows 
    --cpu 2 
    --memory 4
    1. Using ACR:

      1. Go back to Azure Portal

      2. Navigate to Your Container Registry

        In the left sidebar, select "All services" and search for "Container registries".

        Click on your desired ACR instance from the list.

      3. Access the Access Keys Section

        In the ACR blade, find and select "Access keys" in the left menu.

      4. View or Enable Admin User

        By default, the Admin user is disabled for security reasons.

        To generate access keys, toggle Admin user to Enabled.

      5. Copy Username and Passwords

        After enabling, you will see:

        Username (usually the registry name)

        Password and Password2 (two interchangeable passwords)

az container create   --resource-group <resource-group-name>  
--name <aci-name>  
--image <acr-name>.azurecr.io/<image-name>:<version>   --registry-login-server <acr-name>.azurecr.io   
--registry-username <username-from-accesskeys>  
--registry-password <password-from-accesskeys> 
--dns-name-label <desired-site-name> 
 			--ports 8080 8081 
--os-type Windows --cpu 2 
--memory 4
  1. Navigate to the deployed app. In any browser navigate to: http:// ..azurecontainer.io:/

Important considerations

Current SKS app requires a to run in a mcr.microsoft.com/dotnet/sdk:9.0-windowsservercore-ltsc2022 image because migrated app and dcp classes are compiled using Microsoft.WindowsDesktop.App runtime:

This tells .NET to target the Windows Desktop runtime, which is not included in the ASP.NET Core runtime images (mcr.microsoft.com/dotnet/aspnet).

The aspnet image only includes Microsoft.AspNetCore.App and Microsoft.NETCore.App, not Microsoft.WindowsDesktop.App.

Under normal circumstances build and runtime images are different for optimization purposes:

Windows Desktop apps (WPF/WinForms) are not designed to run in containers—they require a Windows session and often access the UI, which is not available in containers. Blazor projects should not require the Windows Desktop runtime unless you are using desktop-specific APIs.

Telerik.UI for Blazor Trial is currently being obtained from a local repository because windows image cannot access https://ais-build-w7.artinsoft.com:8625/nuget/researchExternal/v3/index.json and public feed doesn’t have the required version https://nuget.telerik.com/v3/index.json . The issue with ais probably has to do with network security constraints such as firewalls, antiviruses or certificates. Possible solutions: consume the package from a public feed such as packages.mobilize or fix the network connection issue between the container and ais server.

Last updated