Setting up a .NET 5 web API + Running it in Docker // for beginners
Tags: dotnet, docker, webdev, programming
Published: 2021-09-27 23:13:31

Hey there! 👋🏼

In this tutorial, we'll be setting up a .NET 5 web API and running it locally, then we'll take a look at how to build and run it inside of a Docker container.

To set up the project, we'll be using the dotnet CLI -- which is cross-platform and is included with .NET 5 SDK!

## Why web API?

The .NET team has provided multiple useful templates that can be used when creating a project. Whenever you choose one of them, they set up the project skeleton pre-made to include commonly used packages and folder structure (this is called _scaffolding_).

We're using the `webapi` template to help scaffold our project. The web API template is a great starting point for building out a standard API because it sets you up with a common folder structure.

It also doesn't bloat your project with any extra packages, other than `Swashbuckle.AspNetCore` for [Swagger](https://swagger.io/docs/specification/2-0/what-is-swagger/) support.

We'll be using Swagger to see if our API is running locally.

## Prerequisites

- [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) 
- [Docker](https://www.docker.com/products/docker-desktop)

Once the .NET 5 SDK and Docker are installed, you should be able to use the CLI commands. 

To check, you can run these:

```bash
dotnet --version
```

```bash
docker --version
```

If those return the version, you should be ready to go!

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632533752780/OepdHgwmn.png)

If you see an error message saying your system doesn't recognize `dotnet` or `docker`, make sure it's installed properly for your system. You may need to refresh your terminal so it has access to the command line PATH.

## Running the project locally

Let's run `dotnet new webapi -o <folder>`. The folder is what you want your project to be called; mine is called `AdventureWorks.Api`. Feel free to use that 👍🏼

```bash
dotnet new webapi -o AdventureWorks.Api
```

After a few seconds, the project should be created and all set!

To test out the project and see it in action, in the project folder run:

```bash
dotnet run -p AdventureWorks.Api
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632624601836/fdyi5AniywE.png)

This will build out the project and start a local development server on your computer on (by default) port 5001. Let's check it out by going here:

`https://localhost:5001/swagger`
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632619894607/LfCn8HZps.png)

Cool, the API is up and running locally!

## Running the project in a Docker container

We'll now go over how to run the project within Docker. The difference here is that we'll set up instructions for Docker to do the work of:
- **building the project** - gathering dependencies and compiling
- **publishing the project** - preparing and optimizing it for "release"
- **creating the running docker container** - contains the running web API project

The reason all these steps are used, instead of the steps used to run it locally, is that this is how you'd bundle a typical project in .NET for production. Meaning this way of building the docker image, and running a container based on that image, is optimized and ready to be shipped to users.

This docker build can be used to build out projects for real-world use!

### Let's try it

Create a file, called `Dockerfile`, which will contain the Docker build instructions.

Then paste the following:

```Dockerfile
# Base image used to create the final image
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

# Build image which builds the project and prepares the assets for publishing
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["AdventureWorks.Api.csproj", ""]
RUN dotnet restore "./AdventureWorks.Api.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./AdventureWorks.Api.csproj" -c Release -o /app/build

# Publish image which sets up the optimized version of the app into a folder
FROM build AS publish
RUN dotnet publish "./AdventureWorks.Api.csproj" -c Release -o /app/publish

# Final image which only contains the published content of the project
# This is where the resulting files of the published app are moved to
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AdventureWorks.Api.dll"]
```

_Note: There are comments included for each segment so we can understand what Docker is doing in each step._

This `Dockerfile` now contains all the necessary steps for building out the image which will be used to run the app in a container. To build the docker image using the `Dockerfile`, within the project folder run:

```bash
docker build -t adventureworks.api .
```

Breakdown:
- `docker build` - Used for building docker images from Dockerfiles
- `-t adventureworks.api` - This adds a tag name to the image `adventureworks.api`
- ` .` - This is saying the Dockerfile is located here

After loading and going through the steps, docker should have downloaded all required dependencies and followed the steps within the Dockerfile.

There should now be an image created with a repository named `adventureworks.api`.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632713050569/BVZLYGZh_.png)

This is great, this is the final image that we're after which uses as little space possible. Running a container based on this image should be the published version of the app!

To run this image, run:

```bash
docker run -p 5151:80 adventureworks.api
```

Breakdown:
- `docker run` - Used for running a process in an isolated container
- `-p 5151:80` - Tells docker to map our local port 5151 to port 80 within the container (which is exposed during the build process in our Dockerfile!)
- `adventureworks.api` - The target image to use as a blueprint for the created container

_Note: You may have noticed we're now using port **5151** this time. This is to help us distinguish local, or container, by having them on different ports!_

You should see something like this:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632713810333/SohpGwLZi.png)

The app is now up and running within a docker container! 🎊🎉

To check out the app running in the docker container, we actually can't use the swagger page like before because this app is a release version. Swagger is set up in the `Startup.cs` file to only run in development mode!

We can see the app running by navigating to:

`http://localhost:5151/weatherforecast`
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632714255941/1GVmhzEEe.png)

_Note: It's using `http://` because the app hasn't been set up to use `https://` in the container._

If you've followed along this far and see the data from that endpoint, congrats! You've successfully run the API in a container! 😎

## Closing thoughts

Thank you so much for coming this far in this tutorial! 😀

To recap, we've:
- built a simple .NET 5 app and ran it locally
- ran the app within a docker container

_If you're new to Docker, be sure to clean up any unused containers, images, and resources that you no longer need (if you want to free up storage space). You can learn more about that [using the official docs](https://docs.docker.com/config/pruning/)._

______

I hope you've enjoyed this tutorial or found it helpful. If you did, please let me know. Feedback and comments are welcome!

You can get in touch with me on [Twitter](https://twitter.com/salehmdev). Follow if you'd like to see more content like this, your support is greatly appreciated! 🔥

<a href="https://twitter.com/salehmdev?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-show-count="false">Follow @salehmdev</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

I'd love to hear your thoughts. ✌🏼

## Resources

- https://docs.microsoft.com/en-us/dotnet/core/docker/build-container?tabs=windows