- Published on April 8, 2017
- Tags: programming, asp.net, docker
This website is powered by ASP.NET Core and Postgres running inside a Docker container hosted on Heroku as of this writing. Below are the why's and how's.
Why's
Why ASP.NET Core
In short: cross-platform & lightweight development.
I can code on my Linux desktop and my Windows surface. It's certainly a lot more cross-platform than the Ruby community. Heck, half the gems can't even be installed on Windows.
I was able to write all the components for this website using just Sublime Text and the command line:
- A .NET Core friendly ORM (don't ask why)
- The core logic contained in a .DLL project
- The MVC controllers and views
Why Docker
Docker allows me to have a local environment that's (mostly) identical to the production environment.
Why Heroku
Easy deployment, cheap (enough).
Why Postgres
Cross-platform, the defacto supported database on Heroku, cheap (enough).
How's
Developing ASP.NET Core with Docker
What I do is basically spin up a Docker node with:
- A database container
- A web container, with the
/opt/app
folder mapped to my source code folder. - Configure all this with a
docker-compose.yml
file (see below). - Run
docker-compose run web bash
. This puts me on the bash command line of the web container. From there, I can do my regulardotnet restore
anddotnet watch run
. - From the web container, I can reach the database container via "postgres://db"--you get the idea.
- In the docker-compose file, I mapped port 5000 from the web container and ported 5432 to the same ports on my local machine. This means I can browse the web page I'm developing at "http://localhost:5000" and connect to Postgres via "localhost:5432".
- By default, ASP.NET Core listens at "localhost:{PORT}". This means the web host can only be reached from within the machine or container it runs on. We want to change it to "0.0.0.0:{PORT}". That can be accomplished by setting the
ASPNETCORE_URLS
environment variable, or callUseUrl
when setting up the web host.
Packaging as a Docker image
Microsoft has a comprehensive guide to packaging your .NET Core application using the runtime image (which is significantly smaller than the SDK image). In short:
- Configure your Dockerfile similar the Dockerfile below.
- Run
dotnet restore
thendotnet publish -c Release -o out
to build your binaries. - Run
docker build -t <your-image-name> .
to build the docker image with the binary output.
Pushing YOUR Docker image to Heroku
Heroku also has an official guide to deploy existing Docker images to its infrastructure. Follow the guide to install the Heroku CLI and sign into the container registry from the command line. These two final steps will get your container onto Heroku:
docker tag <your-image-name> registry.heroku.com/<heroky-app-name>/web
docker push registry.heroku.com/<heroky-app-name>/web
If your .NET Core application is a background/command line application, change the last part of the registry to "worker" instead of web.
Note: The first time pushing your docker image to Heroku might take a little while, since it's pushing the whole OS, the .NET Runtime, then your code, etc. Subsequent pushes will only push your code to the registry. The other layers (OS, .NET) are cached on Heroku.