Deploy a Containerized ASP.NET Core App to Heroku using GitHub Actions

First, you need to register an account with heroku.com. Then in your main dashboard, you can create a new app by following the steps in the screenshot below.

The app name is your choice, and it can be modified later. The app name should be unique across the internet because it determines our app’s public URL: https://{$APP_NAME}.herokuapp.com. Of course, you can always provide your own domain name in order to customize the default URL.

Now, we need to get an API key for the continuous deployment process in the GitHub Actions. It’s located at the “Account Settings” page, as shown in the screenshot below.

Copy the API key from Heroku to our GitHub repository as a secret. The screenshot below shows the steps of saving an encrypted secret HEROKU_API_KEY.

Now, we are ready to play with GitHub Actions.

At this point, we can build a docker image as a source and we have a Heroku app as a destination. What’s missing is a way to ship our image to the Heroku container registry and release it to our Heroku web app.

In this project, we will use GitHub Actions to do the work. We create a workflow like the following main.yml file.

gist link

Line 1 is the workflow name definition. Lines 3 to 7 defines the events that trigger the workflow, which are all the push events on the master or release branches. You can learn more about event triggers from this page.

Line 9 starts the jobs definition. In this workflow, we only need one job which is named “build_icolors” in line 10. Line 11 says this job will run in a ubuntu-16.04 virtual environment. In a default workflow template, GitHub Actions will set the virtual environment as ubuntu-latest. However, the newer version of ubuntu OS breaks the MSBuild step. You will see an error message of “Microsoft.Build.BackEnd.NodeFailedToLaunchException: The FileName property should not be a directory unless UseShellExecute is set.”.

This error has been discussed in this issue. The current solution is to use an older version of ubuntu, e.g., ubuntu-16.04. At the time of writing, the linux kernel bug fix is in progress and a patch is submitted (link). I think we can expect a release of new linux kernel soon.

Line 12 begins the definition of steps in this job. The first step, line 13, is to check out the source code. Then the second step, named in line 14, is “Build and deploy the Docker image”. In this step, we set up two environment variables in lines 16 and 17, and we run a set of commands from line 19 to line 22.

One of the two environment variables is the HEROKU_API_KEY, which has a value set in the GitHub repository secrets. The other environment variable is the APP_NAME, icolors, which is the name I set for my Heroku app. The app name will be used in many commands, so it’s better to call it out and refer to it as a generic variable $APP_NAME.

Line 19 changes the current working directory to the solution folder, which is the same folder where the Dockerfile lives. Line 20 builds the docker image. Lines 21 and 22 are Heroku related docker commands. The command heroku container:push will build and tag the docker image for us. Note that, it requires a Dockerfile in the current working directory. You can learn more about deploying a Heroku app with docker from here. Note that the Heroku CLI might change over time, so please always come back to this documentation page for reference.