This weekend I decided to try setting up a simple Web API with .NET Core and Docker running it on Linux. The process was really straightforward. I got it up and running almost immediately. So I decided to share the process.
Set up Docker
I began setting up Docker on my Windows 10 computer. I only have Windows 10 Home so I don’t have Hyper-V so I had to set up Docker Toolbox, which uses VirtualBox as a VM. If you have Windows 10 Pro/Enterprise version of Windows 10 (with Hyper-V) I would recommend Docker for Windows instead.
After setting up Docker I recommend running Docker Quickstart Terminal. It will set everything up for you. You could also run Kitematic which is a GUI and comes with Docker Toolbox. It will also set everything up for you.
Set up .NET Core SDK
Next you need to download the .NET Core SDK to be able to create .NET Core projects and use the dotnet CLI.
Create a Web API project
Next you need to create a .NET Core Web API project. I would recommend choosing the Web Application (.NET Core) otherwise you’re depending on the .NET Framework will only be able to run it on a Windows platform.
Next you can choose a scaffolding template. I chose Web API because I only want to create a simple API without MVC and views.
Now it will create your .NET Core Web API project.
The .NET Core tooling package is awesome and comes with a dotnet command line utility which you can use to create new projects, build and run them, package and publish them. Check out the documentation for more details. We will for now only be using
Running the API
Go into your project directory and type the following:
dotnet restore dotnet build dotnet run
This will restore/retrieve all packages you have defined in package.json, build the project and run it. You should see something like the following:
Now go to //localhost:5000/api/values and you should see some values. By default it will run the API on port 5000 but we’ll change that later on.
To turn off the API just press CTRL+C.
Dockerizing the API
Creating a Dockerfile
Now to the fun part, Dockerizing the API! The API runs on an isolated webserver called Kestrel and as a foreground job, which makes it work really well with Docker.
Go ahead and create a new
Dockerfile in your project directory with the following content:
FROM microsoft/dotnet:latest COPY . /api WORKDIR /api RUN ["dotnet", "restore"] RUN ["dotnet", "build"] ENV ASPNETCORE_URLS //*:5000 EXPOSE 5000/tcp ENTRYPOINT ["dotnet", "run"]
Let’s go through this step by step.
Pull the latest
microsoft/dotnet Docker image and build on top of that. We use that as a base because it contains .NET Core SDK, dotnet CLI, Kestrel webserver, etc.
COPY . /api
Copy everything in the current directory (.) to a new directory
/api in our new Docker image. This is basically just copying our Web API project into the new Docker image.
Set the working directory as our
/api directory where our Web API project lives, so all commands will be executed there.
RUN [“dotnet”, “restore”]
dotnet restore command, which will restore all packages defined in our project.json file.
RUN [“dotnet”, “build”]
dotnet build command, which will build our project.
ENV ASPNETCORE_URLS //*:5000
Set an environment variable
ASPNETCORE_URLS defining the listening port for our API. This is where you can change your listening port to whatever you desire. The
* just binds the listener to all interfaces. I think you can also use
Just informs Docker that the container listens on the specified network ports at runtime. Change this to whatever value you defined in the
ASPNETCORE_URLS environment variable.
ENTRYPOINT [“dotnet”, “run”]
Set the entrypoint for our Docker image, so each time we run the container it executes
dotnet run, which fires up our Web API.
Building a Docker image
Next we’ll create a Docker image based on our Dockerfile. Just go ahead and type the following in your project directory:
docker build -t myapi .
This will build a new Docker image called
myapi based on your current directory (.) and your Dockerfile.
After the image has been built you can type
docker images to list your images. You should see something like this:
If you get an error you probably have to connect the Docker Engine to your VM. You can do that by typing
docker-machine envand following the instructions.
Running a Docker container
Next we’ll run our Docker image in a new Docker container. Just type the following:
docker run -d -p 5000:5000 myapi
This will run the
myapi Docker image in a new detached container exposing port 5000 from the host to port 5000 in the container and output the ID (some hash) of your new container.
Now to make sure your container is running type:
docker ps. You should see something like this:
To stop the container you can just type
docker stop with your container ID or name (obtained via
docker ps). To start the container again you can just type
docker start with your container ID or name.
I recommend you use
--name name_of_containerwhen running your Docker containers so you get a unique name, otherwise Docker generates some gibberish, like in this case evil_wing.
Browsing your API
Now based on how you’re running Docker you need to find the IP address of your VM. If you’re running Docker via Hyper-V you should be able to run //localhost:5000/api/values
If you’re not running Docker via Hyper-V and using Docker Machine with VirtualBox or something, you can type
docker-machine ls which will show the VM you’re running and its IP address. Then you should see something like this:
As you can see my VM has IP 192.168.99.100 so my API is accessible on //192.168.99.100:5000/api/values
Publishing the image on Docker Hub
If you would like to publish your Docker image or run it on another computer, I recommend using Docker Hub. You get one private repository for free but unlimited public repositories.
Just create an account, then type
docker login and enter your username and password in the prompt.
When you type
docker ps you can see that your image name is
myapi. Now that we have a Docker Hub account we have to rename the images so it’s connected to our account name. My docker account name is gaui so I type the following:
docker tag myapi gaui/myapi
Now I can push my image to my Docker Hub account, with the following command:
docker push gaui/myapi
And you should see the following:
And it shows up on my Docker Hub:
Then on my other server I can just type
docker pull gaui/myapi and run it.