Docker for .NET Developers: A Practical Guide

Victor Magalhães
7 min readSep 6, 2023

--

Docker is a software platform that has transformed the way we build, run, and manage applications. It has brought a significant innovation through container technology, providing isolated environments containing everything needed to run an application: code, libraries, and the operating system. This has made it possible to run applications consistently and reliably on any machine with Docker installed, regardless of the underlying operating system.

Key Docker Components

  • Image: Files that encapsulate applications and their dependencies. These images are reusable and shareable, speeding up the development, testing, and deployment of applications, ensuring consistency across different environments.
  • Container: Isolated runtime environments created from images. Containers are remarkably lightweight and portable, making them ideal for running applications at scale, ensuring consistency across different environments.
  • Dockerfile: Text files that serve as guides for building Docker images. They describe the configuration and necessary steps to create a specific image, including defining filesystem layers, specifying dependencies, and including commands for image construction.
  • Docker Hub: A public registry service maintained by Docker, Inc., serving as a central repository for thousands of ready-to-use Docker images. Developers share their own images on Docker Hub, fostering a collaborative community that eases the sharing of solutions and expedites application development.

In summary, Docker has introduced a significant shift in how applications are packaged, distributed, and executed, resulting in increased development efficiency and deployment reliability. With its container-based approach, Docker is redefining application virtualization standards and has become an indispensable tool for development and operations teams worldwide.

Install Docker

Docker

Ensure that Docker is installed on your system. You can download it from the official Docker website (https://www.docker.com/get-started) and follow the installation instructions for your operating system.

Verifying Proper Docker Installation

To check if Docker has been installed correctly, follow these steps:

Check Docker Version: Open a terminal or command prompt and execute the following command to check the installed Docker version:

docker --version

This should display the Docker version installed on your system, indicating that Docker recognizes your command.

Run the Hello World: Docker provides an image called “hello-world,” which is commonly used to test the installation. You can run a container from this image to verify if Docker is functioning correctly. Execute the following command:

docker run hello-world

Docker will download the “hello-world” image if it’s not present locally and then run a container that displays a greeting message. This will confirm that Docker is configured and operational.

If you can successfully complete these steps without errors, it typically indicates that Docker has been installed correctly on your system. Ensure that Docker Desktop or the Docker service (on Linux) is running and configured properly. Remember that some Docker operations may require administrator privileges or access to specific groups, depending on your operating system, so make sure to follow the appropriate installation instructions for your environment.

Creating a Dockerfile for a .NET C# Project

Microsoft .NET

A Dockerfile is an essential component when using Docker to package and deploy applications. It contains instructions for building a custom Docker image that can be used to run your .NET C# application in a container.

Creating a Dockerfile

First, create a file named Dockerfile in your .NET project. It’s common for this file to be in the root directory or in the same directory as the application’s .csproj file.

To make things easier, we’ll have this organization in the project, and based on this organization, we will build our Dockerfile:

MyAPI
Api.sln
/src
Program.cs
Dockerfile
api.csproj
/Controllers
HealthCheckController.cs

Now let’s create the Dockerfile:

# Build Stage
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
COPY ./src/api.csproj ./
RUN dotnet restore
COPY . .
RUN dotnet publish ./src/api.csproj -c release -o build
# Runtime Stage
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
COPY --from=build /app ./
ENTRYPOINT [ "dotnet", "./build/api.dll" ]

Build Stage

The build stage in a Dockerfile is responsible for creating a temporary image that contains all the necessary tools and dependencies to compile, build, and publish your application. This is done separately from the runtime stage to ensure that the resulting image is optimized and contains only the artifacts required for running the application, reducing the final image size.

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build

Sets the base image for the build stage. It uses a .NET SDK 7.0 image for compiling the application.

WORKDIR /app

Sets the current working directory to /app inside the container.

COPY ./src/api.csproj ./

Copies the api.csproj file from the local directory to the /app directory inside the container.

RUN dotnet restore

Executes the dotnet restore command to restore project dependencies based on the api.csproj file.

COPY . .

Copies all the contents from the local directory to the /app directory inside the container.

RUN dotnet publish ./src/api.csproj -c release -o build

Compiles and publishes the application using the api.csproj file, “release” configuration, and outputs the result to the build directory.

The result of the build stage is a temporary image that contains the compiled application and build artifacts. This image will be used later in the runtime stage to create the final container image that will be used to run the application.

Runtime Stage

The runtime stage in a Dockerfile is responsible for creating the final container image that is optimized for running the application. This stage is separate from the build stage and focuses on including only the necessary components and artifacts needed to execute the application while minimizing the image size.

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base

Specifies the base image to be used for the runtime stage, in this case, a .NET ASP.NET image optimized for running applications.

WORKDIR /app

Sets the working directory inside the container to “/app,” where the application files will be placed.

COPY — from=build /app ./

Copies the contents from the build stage (the temporary image created in the build stage) into the working directory of the runtime container. This includes the compiled application code and build artifacts.

ENTRYPOINT [ “dotnet”, “./build/api.dll” ]

Defines the entry point command that will be executed when the container is started. In this case, it specifies that the application should be launched using the dotnet command, and it points to the api.dll file within the “build” directory.

The runtime stage creates a container image that contains only the essential components required to run the application. It leverages the build artifacts produced in the build stage to ensure that the image is as small as possible while still allowing the application to execute successfully. This separation of stages helps reduce the final image size and minimizes potential security vulnerabilities by excluding unnecessary development tools and dependencies.

Building Docker Images

Building a Docker image is the process of creating a self-contained package that includes an application and all its dependencies, following instructions from a Dockerfile. This image is used to create containers that run the application in isolation.

Run this command in the directory where your Dockerfile is located:

docker build -t my_project .

docker build

This is the primary Docker command used to build images.

-t my_project

The -t (or — tag) option is used to specify a name and optionally a tag for the image being created. In the given example, “my_project” is the name of the image.

.

This means Docker will look for a Dockerfile in the current directory (the directory where you are running the command). It’s in this Dockerfile that instructions for building the image are defined.

Checking Docker Images

Verify whether the image you created appears in the list of Docker images on your system. You can list images using the following command:

docker images

This will display a list of available Docker images on your system. Make sure the image you want to run is listed.

Running Docker Images

Running a Docker image means creating and starting a Docker container based on that image. A container is a running instance of the image, executing an application or service within an isolated and self-contained environment. This approach ensures consistency and portability when running applications in various environments.

Run a container with the image:

docker run -d -p 8080:80 my_project

docker run

This is the fundamental command for launching a Docker container.

-d

This option instructs Docker to run the container in the background, meaning it won’t occupy your terminal. It’s beneficial when you want the container to keep running but don’t want it to interfere with your command line.

-p 8080:80

This option is used to establish a port mapping between your host (your machine) and the Docker container. The format is -p hostPort:containerPort, where hostPort is the port on your machine, and containerPort is the port within the Docker container. In the given example, Docker is mapping port 8080 on your host to port 80 within the container. This allows you to access the service running in the container on port 80 by using localhost:8080 in your web browser.

my_project

Replace this with the name of the Docker image you wish to use to create the container. This image serves as the basis for creating the container.

In summary, the command docker run -d -p 8080:80 my_project starts a container using the specified image, runs it in the background, and establishes a port mapping that connects port 8080 on your host to port 80 within the container. This is particularly handy when you want to run applications in Docker containers and access them through your web browser or other applications on your computer.

After running the Docker image, the API will be readily available and accessible for interactions. You can start using the API’s features as soon as the container is up and running.

Conclusion

Docker is a game-changing technology that simplifies the development, deployment, and management of applications. It achieves this by using containers, which are isolated environments containing everything necessary to run an application, making it consistent and reliable across different systems. Key components of Docker include images, containers, Dockerfiles, and Docker Hub, each serving a crucial role in the containerization process.

To leverage Docker, one must install it, verify the installation, and create Dockerfiles to define how images should be built. Building images, checking them, and running containers are essential Docker commands that facilitate the development and deployment of applications. Once an image is running as a container, the API becomes instantly accessible, providing a powerful and flexible way to manage and scale applications.

Docker’s impact on software development and deployment cannot be overstated, making it an indispensable tool for development and operations teams worldwide.

--

--