- 
                Notifications
    
You must be signed in to change notification settings  - Fork 0
 
.NET weatherapi application pushed to ACR and deployed to AKS using GitHub Actions
        ivan edited this page Jun 29, 2025 
        ·
        2 revisions
      
    - first set the secrets in your repo settings
 - head on over to actions and run the pipeline
 - this should send the container to ACR
 
- docker pull acrcrg.azurecr.io/aspcoresample:<image_id_from_acr>
 - then to run the image
 - docker run -p 8080:8080 -e WEATHER_API_KEY=your_key acrcrg.azurecr.io/aspcoresample:1b214a811629ad5572caa8790bec50e805b660b4
 - Then as above head on over to a local browser and so and so
 
az login
az aks get-credentials --resource-group crg --name akscrg
kubectl get pods
kubectl create secret generic weather-api-secret --from-literal=WEATHER_API_KEY=ENTER_YOUR_ACTUAL_KEY_HERE
kubectl apply -f deployment.yaml
kubectl get svcif youd prefer forwarding it locallly and testing it
kubectl port-forward svc/weather-api-service 8080:80go to the public ip and forward the query as before
to stop the server temporarily scale to 0
 kubectl scale deployment weather-api --replicas=0and to resume
kubectl scale deployment weather-api --replicas=1FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
#Improve layer caching and rebuild time
COPY *.csproj ./
RUN dotnet restore
# Copy everything and restore dependencies
COPY . .
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
# Copy the published app from build stage
COPY --from=build /app/out ./
# Expose port 80
EXPOSE 80
#Runtime environment variables
ENV ASPNETCORE_ENVIRONMENT=Production
ENV WEATHER_API_KEY=__REPLACE_AT_RUNTIME__
# Run the app
ENTRYPOINT ["dotnet", "WeatherAPIWrapper.dll"]
name: Build and Push The dotnet app
on:
  push:
    branches: [master]
  workflow_dispatch:
jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 8.0.x
      - name: Restore dependencies
        run: dotnet restore
      - name: Build
        run: dotnet build --configuration Release
      - name: Publish
        run: dotnet publish -c Release -o out
      - name: Docker Login
        uses: azure/docker-login@v1
        with:
          login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
          username: ${{ secrets.REGISTRY_USERNAME }}
          password: ${{ secrets.REGISTRY_PASSWORD }}
      - name: Build and Push Docker image
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ secrets.REGISTRY_LOGIN_SERVER }}/weatherapiwrapper:latest
          file: Dockerfile
          build-args: |
            WEATHER_API_KEY=${{ secrets.WEATHER_API_KEY }}
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: weather-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: weather-api
  template:
    metadata:
      labels:
        app: weather-api
    spec:
      containers:
        - name: weather-api
          image: acrrdx40.azurecr.io/weatherapiwrapper:latest
          ports:
            - containerPort: 80
          env:
            - name: WEATHER_API_KEY
              valueFrom:
                secretKeyRef:
                  name: weather-api-secret
                  key: WEATHER_API_KEY
---
apiVersion: v1
kind: Service
metadata:
  name: weather-api-service
spec:
  type: LoadBalancer
  selector:
    app: weather-api
  ports:
    - port: 80
      targetPort: 80az login
ACR_NAME=acrrdx40
AKS_RESOURCE_GROUP=cr_kr_crg
AKS_CLUSTER_NAME=aksclusterrdx40
az aks show --resource-group $AKS_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query identityProfile.kubeletidentity.objectId -o tsv
#The output of above is your kubelet identity
KUBELET_IDENTITY_ID=bf347f0d-52fd-4483-8766-f825952d2bc8
az acr show --name $ACR_NAME --query id --output tsv
#The output of above is your ACR identity
ACR_ID=/subscriptions/82c2d825-ab4e-45b7-98df-2dbb21f39192/resourceGroups/cr_kr_crg/providers/Microsoft.ContainerRegistry/registries/acrrdx40az ad sp create-for-rbac --name "<ENTER_THE_NAME>" --role <ENTER THE ROLE> --scopes /subscriptions/<ENTER_THE_SUBSCRIPTION_UNDER_WHICH>/resourceGroups/<ENTER_THE_RESOURCE_GROUP_UNDER_WHICH> --sdk-auth
## for example, a reference:
az ad sp create-for-rbac --name "gh-aks-deployer" --role contributor --scopes /subscriptions/82c2d825-ab4e-45b7-98df-2dbb21f39192/resourceGroups/cr_kr_crg --sdk-auth- The above should result in an output as so, Creating 'contributor' role assignment under scope '/subscriptions/82c2d825-ab4e-45b7-98df-2dbb21f39192/resourceGroups/cr_kr_crg' The output includes credentials that you must protect. Be sure that you do not include these credentials in your code or check the credentials into your source control. For more information, see https://aka.ms/azadsp-cli
 
{
  "clientId": "your_client_id",
  "clientSecret": "your_client_secret",
  "subscriptionId": "your_subscription_id",
  "tenantId": "your_tenant_id",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
  "resourceManagerEndpointUrl": "https://management.azure.com/",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com/",
  "managementEndpointUrl": "https://management.core.windows.net/"
}- and then head on over to repo secrets and add the above json as a secret with the Name AZURE_CREDENTIALS
 - Then update the .github/workflow/deploy.yml as so
 
name: Build, Push and Deploy .NET Weather API
on:
  push:
    branches: [master]
  workflow_dispatch:
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 8.0.x
      - name: Restore dependencies
        run: dotnet restore
      - name: Build
        run: dotnet build --configuration Release
      - name: Publish
        run: dotnet publish -c Release -o out
      - name: Docker Login to ACR
        uses: azure/docker-login@v1
        with:
          login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
          username: ${{ secrets.REGISTRY_USERNAME }}
          password: ${{ secrets.REGISTRY_PASSWORD }}
      - name: Build and Push Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: Dockerfile
          push: true
          tags: ${{ secrets.REGISTRY_LOGIN_SERVER }}/weatherapiwrapper:latest
          build-args: |
            WEATHER_API_KEY=${{ secrets.WEATHER_API_KEY }}
      - name: Azure Login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Set AKS Context
        uses: azure/aks-set-context@v3
        with:
          resource-group: cr_kr_crg
          cluster-name: aksclusterrdx40
      - name: Create secret in AKS (if not already present)
        run: |
          kubectl create secret generic weather-api-secret \
            --from-literal=WEATHER_API_KEY=${{ secrets.WEATHER_API_KEY }} \
            --dry-run=client -o yaml | kubectl apply -f -
      - name: Deploy to AKS
        run: kubectl apply -f deployment.yaml- and the deployment.yml which would in a typical project structure be in a k8s directory as so,
 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: weather-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: weather-api
  template:
    metadata:
      labels:
        app: weather-api
    spec:
      containers:
        - name: weather-api
          image: acrrdx40.azurecr.io/weatherapiwrapper:latest
          ports:
            - containerPort: 80
          env:
            - name: WEATHER_API_KEY
              valueFrom:
                secretKeyRef:
                  name: weather-api-secret
                  key: WEATHER_API_KEY
---
apiVersion: v1
kind: Service
metadata:
  name: weather-api-service
spec:
  type: LoadBalancer
  selector:
    app: weather-api
  ports:
    - port: 80
      targetPort: 80- 
Now this can be done in two ways a)Manually triggered on github actions b) Detecting changes to ACR using Azure Event Grid and Azure Functions
 - 
The pipeline for ACR to AKS, is attached below
 
name: Deploy .NET Weather API
on:
  workflow_dispatch:
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 8.0.x
      - name: Restore dependencies
        run: dotnet restore
      - name: Build
        run: dotnet build --configuration Release
      - name: Publish
        run: dotnet publish -c Release -o out
        
      - name: Azure Login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Set AKS Context
        uses: azure/aks-set-context@v3
        with:
          resource-group: cr_kr_crg
          cluster-name: aksclusterrdx40
      - name: Create secret in AKS (if not already present)
        run: |
          kubectl create secret generic weather-api-secret \
            --from-literal=WEATHER_API_KEY=${{ secrets.WEATHER_API_KEY }} \
            --dry-run=client -o yaml | kubectl apply -f -
      - name: Deploy to AKS
        run: kubectl apply -f deployment.yaml