Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
23m 51s
Deploying a .NET Core application into a Docker container is a crucial skill for modern developers. Containers offer immutable infrastructure, easy distribution, and lightweight runtime environments. In this in-depth guide, we'll walk through deploying a sample API to a Docker container, and then push it to Docker Hub, following the steps demonstrated in Tim Corey's comprehensive video tutorial: "Deploying to a Container and Docker Hub - Building a Sample API in C#."
Let's explore the process step-by-step, referencing specific timestamps for easy follow-along. This guide includes usage of commands like .NET publish, the docker run command, and terms like base image, runtime image, and container image - all important concepts for deploying a .NET application using Docker.
At the start of the video, Tim highlights the usefulness of a sample app when learning web development. The app includes endpoints like /courses and /health, simulates real-world issues like degraded health checks, and is designed to run on both your local machine and a remote server.
This is a .NET Core app (more precisely an ASP.NET Core minimal API) that can be run and tested easily through Docker containers.
Tim checks that Docker is installed on his local machine, using Docker Desktop. He notes that it's possible to publish directly to Docker Hub without Docker installed locally, but for demonstration, he begins with local deployment.
He shows two Docker images pre-installed:
This base image is around 328 MB and acts as the foundation for our container image. Microsoft hosts these images on their MCR (Microsoft Container Registry) and they support both Linux containers and Windows containers. For this project, Linux is the target operating system.
Tim navigates to the API project folder and runs the following command in the command line:
dotnet publish -p:PublishProfile=DefaultContainer
This command uses the built-in container support in .NET 8 and .NET 9, which removes the need for a Dockerfile. The publish process selects a suitable runtime image and builds a self-contained container image.
Here's what happens under the hood:
The resulting image is about 333 MB (only 5 MB larger than the base).
Once the image is created, Tim uses Docker Desktop to run the container. Internally, the app listens on port 8080. Tim maps that to a random host port by entering 0 in the port configuration.
The container launches with a random name (e.g., elegant_hoover), and the browser opens to display a working API with "Hello World" as the default response.
By browsing to /courses and /health, Tim confirms that the API is functioning. The health check endpoint is useful for simulating a production environment scenario.
To view running containers, you can use the docker ps command in the CLI. Tim deletes the running container and image afterward to demonstrate cleanup.
Next, Tim moves to the cloud deployment portion. He logs in to his Docker Hub account and creates a public repository named thesampleapi.
This is where the Docker image will be pushed so others can pull it using:
docker pull timcorey/thesampleapi:latest
Inside the API's project file, Tim adds metadata to define where and how to publish the Docker image. He adds the following code block:
<ContainerRegistry>docker.io</ContainerRegistry>
<ContainerRepository>timcorey/thesampleapi</ContainerRepository>
<ContainerImageTags>1.0.0;latest</ContainerImageTags>
This prepares the image for a multi-stage build flow in the future, though Tim is keeping things simple for now.
Tim runs the same publish command again:
dotnet publish -p:PublishProfile=DefaultContainer
Initially, the push fails because he forgot to save the .csproj file. After saving and re-running the command, the image uploads to Docker Hub successfully.
In Docker Hub, both latest and 1.0.0 tags appear under the thesampleapi repo. These tags allow flexibility when pulling specific versions.
Tim demonstrates how to pull the image from any machine with Docker installed:
docker pull timcorey/thesampleapi:latest
Thanks to Docker layer caching, the image downloads quickly since most of it already exists from the base image.
To run the image:
docker run -p 0:8080 timcorey/thesampleapi:latest
This maps a random host port to the internal port 8080.
To demonstrate versioning, Tim edits the .csproj file to:
<ContainerImageTags>1.0.1;latest</ContainerImageTags>
He then re-runs the publish command:
dotnet publish -p:PublishProfile=DefaultContainer
Now the Docker Hub repository shows three tags:
Tim explains that despite multiple tags, Docker doesn't store duplicate layers, optimizing disk usage through distinct layers.
Tim emphasizes that once the image is on Docker Hub, you can run it anytime on any machine by using:
docker pull timcorey/thesampleapi:latest
Then use the docker run command to spin it up. When you're finished, clean up with:
docker ps # Get container ID
docker stop <id> # Stop the container
docker rm <id> # Remove the container
docker rmi <image> # Remove the image
He explains this makes it perfect for on-demand development and testing without bloating your local machine.
Tim wraps up by mentioning the next step: deploying this same API to a Virtual Private Server (VPS). He'll walk through mapping a domain and configuring the container to be publicly accessible.
Using Tim Corey's video guide, we've:
This workflow, centered around Docker and .NET, is perfect for building scalable, testable, and shareable applications.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy