How to Dockerize a .Net core application and deploy it to Heroku

Victor Reyes
FAUN — Developer Community 🐾
4 min readMay 27, 2019

--

Dockerize .Net Project

First of all, let’s assume that you are developing a web api or a web page serving the static files through a .Net core web api.

To run locally your project, you have to run on your command line this comnand:

$ dotnet run

And you will see an output like this:

Hosting environment: Development
Content root path: path/to/project/root/folder
Now listening on: http://[::]:5000
Application started. Press Ctrl+C to shut down.

Now to Dockerize this project your Dockerfile should look like this:

Typical Dockerfile for a .Net Core project for local purposes

Note that in the lines 3 and 4 we are telling to dotnet that he has to run in Production mode and bind to the 5000 port. In line 9 we are building the project and the output files will be stored on the publish folder.

To build and run the Docker image/container, these are the commands:

# Build the image
docker build -t Project-Image-Name .
# Run the container
docker run -d -p 5000:5000 Project-Image-Name

In the last command the -p 5000:5000 option can be used as -p 80:5000 to bind the container port exposed (5000) to a host port (80).

This will work either in your local machine or in a cloud server (AWS EC2, Compute Engine by Google Cloud or any VPS).

Publishing on Heroku

The second part is a little less straightforward, but the steps are pretty simple.

Once the Heroku CLI is istalled, you have to login into Heroku and the Heroku Registry.

// Login using credentials (opens a web brower)
$ heroku login
// Or use this for login directly form command line
$ heroku login -i
// Login into Heroku container registry (more about this later)
// Trough Heroku Cli
$ heroku container:login
// Trough Docker Cli
$ docker login --username=_ --password=$(heroku auth:token) registry.heroku.com

Create a Heroku app

This part can be done directly on your Heroku Dashboard

Creating “fancy-project”

Also, you can create the app through the CLI.

// Create an app (on the root of the project), this will create an app with a random name that you can update later
$ heroku create

Now, that the app has been created we can push a Docker image to the Heroku Registry with an url like this registry.heroku.com/<app-name>/<process-type> . In this case as we’ve created a “fancy-project” app with a single Dockerfile (a web process type) the url will be like registry.heroku.com/fancy-project/web .

Remeber that if your project is a multi-container application, every Dockerfile has to be a different <process-type> ( web and worker for free dyno plans).

We could just push the Docker image to the registry and see what happen, but first we have to fix the Dockerfile and our project.

One of the first things that you have to know about deploying Docker images to Heroku is that the are some limitations. In our use case we have to notice two important restrictions.

  1. VOLUME command is not supported. Heroku uses a “ephemeral filesystem” this means that all the files that you upload or save on the container (usually the wwwroot folder) won’t be persistent. You will have to look for another option for storing some static files.
  2. Heroku ignores your EXPOSE command. Heroku dynamically assign a port to your container and just listens to that port (it doesn’t matter if your project tries to bind to ports 80, 8080 or 5000 through EXPOSE or PORT commands) it can be accessed inside the container as echo $PORT .

To workaround the point 1. it’s up to you, but to solve the issue with the second point we have a few things to do.

Update Dockerfile

Dockerfile for a .Net Core project udpated to work with Heroku

Note that we have deleted the VOLUME and the ENV command that used to tell in which port the dotnet had to run. The second part it’s because Heroku will inject a PORT environment variable to the running container (the port that your project will have to use).

Update Program.cs

We have to update the project (specifically the Program.cs file) to dinamically select on which port to run according to that PORT variable.

Program.cs file of .Net Core that reads PORT from environment variables

Note that the line 13 does the same that our first Dockerfile ,ENV ASPNETCORE_URL http://+:5000 but this time we are using the PORT variable injected by Heroku.

Build, Push & Release

Finally it’s time to build the image…

docker build -t registry.heroku.com/<app-name>/<process-type>
...
docker build -t registry.heroku.com/fancy-project/web .

Push to Heroku’s registry…

docker push registry.heroku.com/<app-name>/<process-type>
...
docker push registry.heroku.com/fancy-project/web

Releasing the app

heroku container:release <process-type> --app <app-name>
heroku container:release web --app fancy-project

After a few moments the app will be released and you can manage it from the Heroku Dashboard o access directly from the url (something like <app-name>.herokuapp.com ).

Follow us on Twitter 🐦 and Facebook 👥 and join our Facebook Group 💬.

To join our community Slack 🗣️ and read our weekly Faun topics 🗞️, click here⬇

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇

--

--