Tutorials & Tips

Deploying a .NET Core App with Docker and GitHub Actions on Azure – Complete CI/CD Pipeline

In today’s fast-paced software world, automation is king. Manually deploying updates is time-consuming, error-prone, and inefficient. That’s where CI/CD pipelines come in. In this comprehensive guide, we’ll walk you through creating a complete CI/CD pipeline to deploy a .NET Core application using GitHub Actions, Docker, and Azure Web App for Containers.

You’ll learn how to:

  • Dockerize a .NET Core web application
  • Configure GitHub Actions for CI/CD
  • Push a Docker image to Azure Container Registry (ACR)
  • Automatically deploy the image to an Azure Web App

Whether you’re a developer, DevOps engineer, or cloud enthusiast, this tutorial will give you a powerful, production-ready deployment setup.


🧰 Prerequisites

Before we start, make sure you have the following:

  • A .NET Core application (we’ll use ASP.NET Core 7.0 for this guide)
  • GitHub account with a repository for your project
  • Azure account with access to create a Resource Group and Web App
  • Docker installed on your local machine
  • Azure CLI installed (az command)

Optional but recommended:

  • Visual Studio Code or Visual Studio
  • Basic understanding of Docker and GitHub Actions

🗂 Step 1: Create the .NET Core Web Application

If you don’t have an existing .NET Core app, let’s create a new one:

mkdir MyDotNetApp
cd MyDotNetApp
dotnet new webapi -n MyDotNetApp
cd MyDotNetApp
dotnet run

Ensure everything is working by opening http://localhost:5000.


🐳 Step 2: Dockerize the Application

Create a Dockerfile in the root directory:

# Stage 1 - Build
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o out

# Stage 2 - Runtime
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "MyDotNetApp.dll"]

Test the Dockerfile locally:

docker build -t mydotnetapp .
docker run -p 8080:80 mydotnetapp

Navigate to http://localhost:8080 to ensure it works.


☁️ Step 3: Create Azure Resources

Let’s prepare Azure for the deployment.

az login
az group create --name MyResourceGroup --location eastus
az acr create --resource-group MyResourceGroup --name MyACRRegistry --sku Basic --admin-enabled true
az acr login --name MyACRRegistry

Create an App Service Plan and Web App:

az appservice plan create --name MyAppPlan --resource-group MyResourceGroup --is-linux --sku B1
az webapp create --resource-group MyResourceGroup --plan MyAppPlan --name MyDotNetWebApp --deployment-container-image-name myacrregistry.azurecr.io/mydotnetapp

🔐 Step 4: Store Azure Credentials in GitHub Secrets

Generate credentials for GitHub to access Azure:

az ad sp create-for-rbac --name "github-cicd" --role contributor --scopes /subscriptions/<subscription-id>/resourceGroups/MyResourceGroup --sdk-auth

Copy the output JSON and go to your GitHub repository:

  • Navigate to Settings > Secrets and variables > Actions > New Repository Secret
  • Add a secret with name AZURE_CREDENTIALS and paste the JSON output

Also add secrets:

  • AZURE_WEBAPP_NAME: MyDotNetWebApp
  • AZURE_REGISTRY_NAME: MyACRRegistry

⚙️ Step 5: Configure GitHub Actions

Create a folder structure:

mkdir -p .github/workflows
touch .github/workflows/deploy.yml

Here’s a sample deploy.yml:

name: Deploy to Azure

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Set up .NET Core SDK
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: '7.0.x'

    - name: Log in to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Build Docker image
      run: |
        docker build -t myacrregistry.azurecr.io/mydotnetapp .

    - name: Azure Container Registry Login
      uses: azure/docker-login@v1
      with:
        login-server: myacrregistry.azurecr.io
        username: ${{ secrets.AZURE_REGISTRY_NAME }}
        password: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Push image to ACR
      run: docker push myacrregistry.azurecr.io/mydotnetapp

    - name: Deploy to Azure Web App
      uses: azure/webapps-deploy@v2
      with:
        app-name: ${{ secrets.AZURE_WEBAPP_NAME }}
        images: myacrregistry.azurecr.io/mydotnetapp

Push your changes to GitHub:

git add .
git commit -m "Add CI/CD pipeline"
git push origin main

GitHub Actions will automatically build your Docker image, push it to ACR, and deploy it to Azure.


✅ Step 6: Test Your Deployment

Go to the Azure Portal, open your Web App (MyDotNetWebApp), and grab the public URL. Visit it in your browser and confirm your .NET app is live!

Every time you push to the main branch, the entire pipeline will rerun.


🛠 Tips and Enhancements

  • Add stages for testing (e.g., dotnet test) before deploying
  • Use production and staging environments
  • Monitor deployments via Azure App Insights
  • Use GitHub environments and approvals for production
  • Auto-tag Docker images using GITHUB_SHA or date

📦 Bonus: Auto-Tagging Docker Images

Modify your deploy.yml to include version tags:

- name: Define Docker Tag
  run: echo "IMAGE_TAG=$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV

- name: Build Docker Image
  run: docker build -t myacrregistry.azurecr.io/mydotnetapp:${{ env.IMAGE_TAG }} .

- name: Push Docker Image
  run: docker push myacrregistry.azurecr.io/mydotnetapp:${{ env.IMAGE_TAG }}

🧠 Conclusion

You now have a fully automated CI/CD pipeline using GitHub Actions, Docker, and Azure! This setup enables continuous deployment with minimal manual effort. You can scale this setup to multiple environments, microservices, and even Kubernetes.

Automation is key to modern software delivery. Start small, iterate fast, and keep improving your pipelines. Happy shipping! 🚀

Mohamed Assem

I'm Mohamed Assem, an IT professional with over 14 years of experience. I've worked extensively in infrastructure and server management, as well as software development, particularly with .NET technologies. Currently, I combine both skill sets in my role as a DevOps and Automation Engineer. Through my website, I aim to share my knowledge and make the field more accessible for beginners, helping them navigate the complexities of IT with ease

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button