Image depicting containerizing apps with Docker and deploying with Kubernetes β€” Image source: By Author

Containerizing .NET Core Applications with Docker and Orchestrating with Kubernetes

Merwan Chinta
CodeNx

--

As the need for scalable, efficient, and portable applications is paramount, two tools that have revolutionized this space are Docker and Kubernetes. Docker provides a platform to containerize and deploy applications seamlessly, while Kubernetes offers a robust system for managing and orchestrating these containers.

In this post, we will delve into how to containerize a .NET Core application using Docker and then manage these containers using Kubernetes.

Prerequisites

  • Basic understanding of .NET Core
  • Familiarity with Docker and Kubernetes
  • Docker and Kubernetes installed on your system

Step 1: Creating a .NET Core Application

First, create a simple .NET Core application. If you already have one, you can skip to the next step.

dotnet new webapi -n MyNetCoreApp
cd MyNetCoreApp

This command creates a new .NET Core Web API project.

Step 2: Dockerizing the .NET Core Application

Create a Dockerfile: In the root of your .NET Core application, create a file named Dockerfile.

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "MyNetCoreApp.dll"]

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build: This line starts the first stage of the build. It pulls the .NET Core 3.1 SDK image from Microsoft Container Registry (MCR). This image includes the .NET Core SDK, which is necessary for building .NET Core applications. The AS build part names this stage "build".

COPY *.csproj ./: Copies the C# project file (.csproj) into the container's /app directory.

RUN dotnet restore: Restores the NuGet packages specified in the .csproj file. This is necessary for building the application.

COPY . ./: Copies all the other files in the application's directory into the container's /app directory.

RUN dotnet publish -c Release -o out: Publishes the application in "Release" configuration and outputs the compiled files to the out directory inside the container.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1: This line starts the second stage of the build. It pulls the .NET Core 3.1 ASP.NET runtime image from MCR. This image is optimized for running ASP.NET Core applications but does not include the SDK.

WORKDIR /app: Sets the working directory to /app in the new container.

COPY --from=build /app/out .: Copies the compiled application from the out directory of the build stage into the current working directory of the new stage.

ENTRYPOINT ["dotnet", "MyNetCoreApp.dll"]: Specifies the command to run when the container starts. In this case, it runs the .NET Core application using dotnet MyNetCoreApp.dll.

Build the Docker Image

Run the following command to build the Docker image.

docker build -t mynetcoreapp .

Run the Container

Once the image is built, run it using.

docker run -d -p 8080:80 --name mynetcoreappcontainer mynetcoreapp

Step 3: Deploying to Kubernetes

Create a Kubernetes Deployment Configuration: Create a file named deployment.yaml with the following content.

apiVersion: apps/v1
kind: Deployment
metadata:
name: mynetcoreapp-deployment
spec:
replicas: 2
selector:
matchLabels:
app: mynetcoreapp
template:
metadata:
labels:
app: mynetcoreapp
spec:
containers:
- name: mynetcoreapp
image: mynetcoreapp:latest
ports:
- containerPort: 80

apiVersion: apps/v1: Specifies the API version of the Kubernetes resource. Here, apps/v1 is the API version for Deployment resources.

kind: Deployment: Indicates the kind of Kubernetes resource being defined. In this case, it's a Deployment, which ensures that a specified number of pod replicas are running at any given time.

metadata: Provides metadata section about the Deployment.

name: mynetcoreapp-deployment: Sets the name of the Deployment. This name is used to reference the Deployment within the Kubernetes cluster.

spec: Contains the specification of the Deployment.

replicas: 2: Specifies that there should be 2 replicas of the pod running at all times.

selector: Defines how the Deployment finds which Pods to manage.

matchLabels: This part of the selector ensures the Deployment manages pods that have labels matching the specified criteria.

app: mynetcoreapp: This label is used to link the Deployment with Pods that have the same label.

template: Specifies the pod template that the Deployment will use to create new pods.

metadata and labels: Defines the metadata for the pods. Here, it assigns a label (app: mynetcoreapp) to all pods created using this template, which connects them to the Deployment via the selector.

spec: The specification for the pods to be created.

containers: A list of container specifications within the pod.

name: mynetcoreapp: Sets the name for the container.

image: mynetcoreapp:latest: Specifies the container image to use. In this case, it's using an image named mynetcoreapp with the latest tag.

ports: Specifies the port configuration for the container.

containerPort: 80: Indicates that the container is listening on port 80.

Deploy to Kubernetes

Apply the configuration using.

kubectl apply -f deployment.yaml

Create a Service

To expose your application, create a service service.yaml

apiVersion: v1
kind: Service
metadata:
name: mynetcoreapp-service
spec:
selector:
app: mynetcoreapp
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer

apiVersion: v1: This specifies the version of the Kubernetes API you're using. v1 is a widely used version for many core Kubernetes resources, including Services.

kind: Service: This indicates that the resource type being defined is a Service.

metadata: This section provides metadata about the Service.

name: mynetcoreapp-service: This sets the name of the Service. It's used to refer to the Service within the Kubernetes cluster.

spec: This section contains the specification of the Service.

selector: This field selects the Pods that the Service will apply to. In this case, it selects Pods with the label app: mynetcoreapp, which should match the Pods created by your Deployment.

ports: This field defines the ports that the Service will expose.

protocol: TCP: Specifies the protocol used by the Service, which is TCP in this case.

port: 80: This is the port that the Service will expose externally. When other components of the cluster or external users access this Service, they will use this port.

targetPort: 80: This specifies the port on the Pods that the Service routes to. In this case, it routes to port 80 on the Pods, which should be the port your application is listening on (as defined in your Deployment).

type: LoadBalancer: This specifies the type of Service. A LoadBalancer Service is used to expose the Service externally. It automatically creates an external load balancer in your cloud provider (if your cluster is hosted on a cloud platform) and assigns a fixed, external IP to your Service. This makes your application accessible from outside the Kubernetes cluster.

Apply the Service Configuration

kubectl apply -f service.yaml

Next?

This post provides a basic walkthrough of the process, but the possibilities with these tools are vast and worth exploring further.

The real power of Docker and Kubernetes comes from their flexibility and scalability, making them ideal for modern application development and deployment.

Containerizing a .NET Core application with Docker and managing it with Kubernetes simplifies deployment, scaling, and management.

I trust this information has been valuable to you. 🌟 Wishing you an enjoyable and enriching learning journey!

πŸ“š For more insights like these, feel free to πŸ‘ follow πŸ‘‰ Merwan Chinta

--

--

Merwan Chinta
CodeNx
Editor for

🚧 Roadblock Eliminator & Learning Advocate πŸ–₯️ Software Architect πŸš€ Efficiency & Performance Guide 🌐 Cloud Tech Specialist