Docker, Deployment, GitHub Actions & CI/CD Masterclass

โšก C# 12 & .NET 8 ๐ŸŸข Chapter 46 of 35 ๐Ÿ“‚ Phase 17: Deployment & Cloud ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Docker ยท Dockerfile Multi-Stage ยท docker-compose ยท GitHub Actions ยท CI/CD Pipeline ยท Build & Test ยท Health Checks ยท Environment Variables ยท Azure App Service

Welcome to Phase 17 (Chapter 46): Docker, Deployment, GitHub Actions CI/CD & Health Checks Masterclass! Building an application is half the job. Deploying it reliably, consistently, and automatically is the other half. In this chapter, we master containerizing ASP.NET Core apps with Docker, writing Dockerfiles and docker-compose, setting up GitHub Actions CI/CD pipelines, configuring production environment variables, implementing Health Checks, and deploying to cloud platforms.

1Docker Ante Enti? โ€” Containers vs VMs
AspectVirtual Machine (VM)Docker Container
SizeGigabytes (includes full OS)Megabytes (shares host OS kernel)
Startup TimeMinutes (boots entire OS)Seconds (process isolation)
Isolation LevelComplete hardware virtualizationProcess-level namespace isolation
PortabilityHypervisor-dependentRuns identically on any Docker host
2Dockerfile for ASP.NET Core API
Dockerfile โ€” Multi-Stage Build for ASP.NET Core
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# Copy project file and restore dependencies
COPY ["ProductsAPI/ProductsAPI.csproj", "ProductsAPI/"]
RUN dotnet restore "ProductsAPI/ProductsAPI.csproj"

# Copy all source and build
COPY . .
WORKDIR "/src/ProductsAPI"
RUN dotnet build "ProductsAPI.csproj" -c Release -o /app/build

# Stage 2: Publish
FROM build AS publish
RUN dotnet publish "ProductsAPI.csproj" -c Release -o /app/publish

# Stage 3: Runtime (smallest possible final image)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProductsAPI.dll"]
YAML โ€” docker-compose.yml
version: '3.9'

services:
  api:
    build: .
    ports:
      - "5000:80"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__DefaultConnection=Server=db;Database=ProductsDB;User Id=sa;Password=YourPass123!
    depends_on:
      - db

  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=YourPass123!
    ports:
      - "1433:1433"
    volumes:
      - sqldata:/var/opt/mssql

volumes:
  sqldata:
3GitHub Actions CI/CD Pipeline
YAML โ€” .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-test-deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Setup .NET 8
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: '8.0.x'

    - name: Restore dependencies
      run: dotnet restore

    - name: Build
      run: dotnet build --no-restore -c Release

    - name: Run Tests
      run: dotnet test --no-build -c Release --verbosity normal

    - name: Build Docker Image
      run: docker build -t productsapi:latest .

    - name: Deploy to Azure App Service
      uses: azure/webapps-deploy@v2
      with:
        app-name: 'my-productsapi'
        publish-profile: DOLLAR{{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
        images: 'productsapi:latest'
4Health Checks & Monitoring
C# โ€” Health Checks Registration โ–ถ Run in Compiler
// Register health checks
builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>()       // Checks DB connectivity
    .AddUrlGroup(new Uri("https://api.github.com"), "GitHub"); // External dependency

// Map health endpoints
app.MapHealthChecks("/health");              // Simple: healthy/unhealthy
app.MapHealthChecks("/health/detailed", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
}); // Detailed JSON report
5Technical FAQs

Q1: Why use multi-stage Docker builds?

Multi-stage builds use the full .NET SDK (large image ~800MB) only during the build stage, then copy the compiled output to a minimal ASP.NET runtime image (~200MB) for the final container. This drastically reduces image size, attack surface, and deployment time.

Q2: How do I manage secrets (connection strings, API keys) in Docker?

Never hardcode secrets in Dockerfiles or docker-compose.yml committed to Git. Use environment variables injected at runtime, Docker Secrets, Kubernetes Secrets, or Azure Key Vault. Use GitHub Actions Secrets for CI/CD pipeline credentials.