.NET Web API Dockerization

Darshana Mihiran Edirisinghe
4 min readOct 3, 2023

--

Step-by-step guide

In the local machine

  1. Install Docker from the docker website: for windows
  2. Create a .NET API project.
  3. Create a Docker file: A Dockerfile is a script that contains instructions for building a Docker image. Below is the sample docker file.
FROM mcr.microsoft.com/dotnet/aspnet:5.0 as base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
COPY . /src
WORKDIR /src
RUN ls
RUN dotnet build "aspnetapp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "aspnetapp.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

4. Build the Docker Image: Open a terminal in your project directory and run the following command to build the Docker image

docker build -t aspnetapp .

5. Run the Docker Container: Once the image is built, you can run a Docker container from it using the following command

docker run -d -p 8080:80 --name aspnetappcontainer aspnetapp

6. Access Your API: The .NET API should now be running inside a Docker container. You can access it by opening a web browser and navigating to http://localhost:8080

7. Stop and Remove the Docker Container

docker stop your-api-container-name
docker rm your-api-container-name

In Azure CI/CD

  1. Create a Build Pipeline: A build pipeline compiles your code, creates a Docker image, and pushes it to a container registry.
  • New pipeline.
  • Select the source code repository.
  • Configure the YAML pipeline.
trigger:
- '*'

pr:
- '*'

pool:
vmImage: 'ubuntu-latest'

steps:
- script: |
docker build -t aspnetapp .
docker push azure-acr-tenant.azurecr.io/aspnetapp:$(Build.BuildId)
displayName: 'Build and Push Docker Image'

env:
DOCKER_CLI_ACI_LOGIN: true

- task: Docker@2
inputs:
containerRegistryType: 'Azure Container Registry'
azureSubscriptionEndpoint: 'your-azure-subscription'
azureContainerRegistry: 'your-acr-name.azurecr.io'
dockerImageName: 'aspnetapp'
imageName: '$(azureContainerRegistry)/aspnetapp:$(Build.BuildId)'
command: 'push'
  • Save and commit.
  • Build Trigger.

2. Create Release Pipeline: A release pipeline deploys your Docker image to Azure services: e.g. Azure App Service

  • New release pipeline.
  • Choose a template/empty to create a release pipeline.
  • Select Artifact source: select the above-created build pipeline.
  • Configure: deployment target: e.g. Azure App Service.
  • Deployment task: Add ‘Deploy Docker Container’ task. configure this to deploy the docker image from Azure Container Registry to Azure App Service.
  • Save and trigger the release.

Summary: Dockerization

  1. Building the Docker Image: The build pipeline is responsible for building the Docker image from your source code.
    This is typically done using a Dockerfile that specifies the instructions for creating the image.
    When you trigger a build, Azure DevOps executes the commands defined in the azure-pipelines.yml to build the Docker image.
  2. Pushing the Docker Image: After building the Docker image, the build pipeline pushes the image to a container registry.
    This is typically an Azure Container Registry (ACR) etc.
  3. In a separate release pipeline, you can pull the Docker image from the container registry and deploy it to your target environment. e.g. An Azure App Service.

It’s common practice to tag Docker images with unique identifiers, such as build IDs or version numbers. This ensures that each image is distinct and can be easily tracked. In the azure-pipelines.yml, you might see an image tagging step like this:

imageName: '$(azureContainerRegistry)/aspnetapp:$(Build.BuildId)'

To push the Docker image to the container registry, the build pipeline must be configured with appropriate authentication credentials. This is typically done using Azure DevOps service connections or secret variables to securely store the necessary credentials for accessing the container registry.

Failures

Identify Dockerfile build failures in an Azure CI/CD pipeline

  1. Proper Error Handling in Dockerfile: If a critical step fails, it should exit with a non-zero exit code. Docker itself will catch this and return an error code to the CI/CD pipeline: RUN some-command || exit 1
  2. CI/CD Pipeline Configuration: In your Azure CI/CD pipeline configuration, you can specify the behavior when a step fails. Typically, CI/CD tools will automatically consider the build as failed if any step returns a non-zero exit code.
  3. Logging and Output: Ensure that the output of the Docker build process is captured and logged by your CI/CD tool. This will help you review the build logs to identify any errors or issues.
  4. Monitoring and Notifications: Configure your CI/CD tool to send notifications or alerts when a build fails.
  5. Continuous Integration Testing: Verify the correctness of your Dockerfile and the resulting image. e.g. You can use linting tools to check Dockerfile syntax.

Identifying errors in a Docker image

  1. Implement automated tests within the Docker container: Unit Tests, Integration Tests
  2. Container Scanning: Scanning tools to check for vulnerabilities and security issues within your Docker image. Azure Container Registry (ACR) provides built-in container scanning capabilities.
  3. Health Checks.

Best Practices

  1. Use Official Docker Images. e.g. Docker Hub
  2. Optimize Docker Images: Keep Docker images as small as possible by removing unnecessary dependencies and files.
  3. Secure Secrets and Credentials: Avoid hardcoding secrets, Use Azure Key Vault.
  4. Use Container Registries
  5. Include automated tests (unit tests, integration tests, etc.) in your CI/CD pipeline to ensure the correctness of your application within the Docker container.

--

--

Darshana Mihiran Edirisinghe

Full Stack Developer | Information Technology Consultant | Scrum Master | Tech Enthusiast