Skip to main content

Hosting ASP.Net Core app on Heroku using Docker

Quick Summary

Today I want to make a small and simple blog post about how to deploy ASP.Net Core application to Heroku using Docker.

Requirements

  1. Docker
  2. Heroku CLI (you will need registered Heroku account)
  3. ASP.Net Core application you want to deploy (I will use the one we've created here)

Create Heroku App

To start, we need to create a blank app from Heroku like this
Choose the name you like and then we are good to go.

Setup Dockerfile

Re-use dockerfile from my previous post
# First we add a dotnet SDK image to build our app inside the container
FROM microsoft/dotnet:sdk AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out

# Here we use ASP.NET Core runtime to build runtime image
FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
CMD ASPNETCORE_URLS=http://*:$PORT dotnet NetCoreExample.dll
NOTE: Because Heroku doesn’t work nicely with ENTRYPOINT command we should change this:
ENTRYPOINT ["dotnet", "NetCoreExample.dll"]
to this:
CMD ASPNETCORE_URLS=http://*:$PORT dotnet NetCoreExample.dll
And don't forget to change NetCoreExample.dll to the name of your application.

Deploy Docker Container to Heroku

First, we need to login to Heroku and Heroku container using these commands:
$ heroku login
$ heroku container:login
While I was doing this, I was constantly getting an error "docker: Got permission denied while trying to connect to the Docker...". If you also get this error, check this StackOverflow question.

Now we should build Docker image using this command:
$ docker build -t netcoreexample .
Where netcoreexample is the name of your app.

We need to tag the heroku target image
$ docker tag netcoreexample registry.heroku.com/test-app-docker/web
Where test-app-docker is the name of the Heroku app, we've created on the first step.

Push the docker image  to Heroku registry
$ docker push registry.heroku.com/test-app-docker/web
And finally deploy it!
$ heroku container:release web -a test-app-docker
Now if you will open link that loos like https://{your-app-name}.herokuapp.com/ you will be able to access you web app.

Summary

Now you can use only 4 commands to deploy your application to Heroku. In future you can add CI system and configure it to do them for you ;)

Thank you for reading and Happy Coding!

Comments

Popular posts from this blog

How to Build TypeScript App and Deploy it on GitHub Pages

Quick Summary In this post, I will show you how to easily build and deploy a simple TicksToDate time web app like this: https://zubialevich.github.io/ticks-to-datetime .

Pros and cons of different ways of storing Enum values in the database

Lately, I was experimenting with Dapper for the first time. During these experiments, I've found one interesting and unexpected behavior of Dapper for me. I've created a regular model with string and int fields, nothing special. But then I needed to add an enum field in the model. Nothing special here, right? Long story short, after editing my model and saving it to the database what did I found out? By default Dapper stores enums as integer values in the database (MySql in my case, can be different for other databases)! What? It was a surprise for me! (I was using ServiceStack OrmLite for years and this ORM by default set's enums to strings in database) Before I've always stored enum values as a string in my databases! After this story, I decided to analyze all pros and cons I can imagine of these two different ways of storing enums. Let's see if I will be able to find the best option here.

Caching strategies

One of the easiest and most popular ways to increase system performance is to use caching. When we introduce caching, we automatically duplicate our data. It's very important to keep your cache and data source in sync (more or less, depends on the requirements of your system) whenever changes occur in the system. In this article, we will go through the most common cache synchronization strategies, their advantages, and disadvantages, and also popular use cases.

How to maintain Rest API backward compatibility?

All minor changes in Rest API should be backward compatible. A service that is exposing its interface to internal or/and external clients should always be backward compatible between major releases. A release of a new API version is a very rare thing. Usually, a release of a new API version means some global breaking changes with a solid refactoring or change of business logic, models, classes and requests. In most of the cases, changes are not so drastic and should still work for existing clients that haven't yet implemented a new contract. So how to ensure that a Rest API doesn't break backward compatibility?