Developing ASP.NET Core apps in Docker - Live Recompilation

Developing ASP.NET Core apps in Docker - Live Recompilation

How to develop dockerized ASP.NET Core application.

October 2022

Introduction

My friend that is a PHP developer showed me docker and how he uses it in the developing process of his app. I learned thanks to it we don’t have to litter our computers installing database servers, for example. Not only previously mentioned advantage encouraged me to learn it but also the fact that he could easily observe and test changes after he made it without rebuilding the docker image and recreating the container.

After gathering a little knowledge of docker I still haven’t enough knowledge to develop my dockerized app without rebuilding the image.

Now thanks to codewithflavor owner - Jan yaneX Kliszcz I achieved it and now I would want to share it.

0. Requirements

  • Docker
  • .NET 6.0

1. Add new profile to launchSettings

"Docker": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "applicationUrl": "http://*:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }

Because HTTPS is not required in the development process and it may cause some problems like System.InvalidOperationException: Unable to configure HTTPS endpoint we create a new launch profile without HTTPS URL and with environment settings to development.

Thanks to * in the URL application will listen to requests coming from any address with indicated port.

2. Create Directory.Build.props

<Project>
    <PropertyGroup>
        <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/obj/**/*</DefaultItemExcludes>
        <DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/bin/**/*</DefaultItemExcludes>
    </PropertyGroup>
    <PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' == 'true'">
        <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/container/</BaseIntermediateOutputPath>
        <BaseOutputPath>$(MSBuildProjectDirectory)/bin/container/</BaseOutputPath>
    </PropertyGroup>
    <PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' != 'true'">
        <BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/local/</BaseIntermediateOutputPath>
        <BaseOutputPath>$(MSBuildProjectDirectory)/bin/local/</BaseOutputPath>
    </PropertyGroup>
</Project>

This file allows us to create a specific configuration that tells the builder to put files after building in different folders when building locally and when building in the container.

Without it, IDE loses its mind and doesn’t detect namespaces from NuGet packages.

Firstly we suppress the default behavior of putting build files to default /bin and /obj paths.

Then we create two property groups with conditions to behave differently depending on the running environment.

3. Create docker-compose file

version: "3.9"

services:
  api:
    container_name: sampleAPIContainerName
    image: mcr.microsoft.com/dotnet/sdk:6.0
    ports:
      - 5001:5001
    volumes:
      - .:/app
    working_dir: /app
    command: dotnet watch run --project sampleProjectName --launch-profile Docker

Finally, we can create docker-compose.

To get the live recompilation we need to set the same port as we set in launchProfile.json

To share files with docker to detect changes made to the files we need to define a volume and set it to docker’s location as working_dir.

In the last step, we launch dotnet watch run with --launch-profile argument to make dotnet watch run to use the previously created launch profile by us.

Now you just need to run docker-compose up to launch the application.

4. Demo on GitHub

Sample API project is available on GitHub

Final thoughts

I hope you find this article helpful.

Connect with me - Linkedin

Follow me - GitHub