Docker dotnet watch run error: Unable to bind to https://localhost:5000 on the IPv6 loopback interface

20,650

Solution 1

Just ran into this problem myself. I don't think dotnet watch run plays nicely with localhost type urls. Try setting your hosting url to https://0.0.0.0:5000 in your container.

In the dockerfile with:

ENTRYPOINT [ "dotnet", "watch", "run", "--no-restore", "--urls", "https://0.0.0.0:5000"]

Or in launchSettings.json like:

{
  "profiles": {
    "[Put your project name here]": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "DOTNET_USE_POLLING_FILE_WATCHER": "true"
      },
      "applicationUrl": "https://0.0.0.0:5000/"
    }
  }
}

Now to get it to automatically reload from within the container you have to use the polling file watcher. That's what the second environment variable is for. (This is pretty common, you've got to do this with webpack, angular, etc).

In your case, you need to change the esportsapp.volume to a directory on your host:

volumes:
  - ./:/app

That will map the /app volume in your container to the docker-compose directory. The problem you're facing is that the app is built in a volume on your project's default docker-compose network, so when you change a file in the source directory, it's not actually changing in that volume. With this fix, however, you'll run into the problem of the dotnet restore and dotnet watch inside the container changing your host's files. There's a fix for all of that, if you're interested...

My Usual .Net Core App Docker setup

To debug, run: docker-compose -f run.yml up --build

To build a release: docker-compose -f build.yml up --build

Project structure

/                                               # source control root
/build.yml                                      # docker-compose file for building a release
/run.yml                                        # docker-compose file for running locally & debugging
/project                                        # an application
/project/build.Dockerfile                       # the docker container that will build "project" for release
/project/run.Dockerfile                         # the docker container that will build and run "project" locally for debugging
/project/.dockerignore                          # speeds up container builds by excluding large directories like "packages" or "node_modules"
/project/src                                    # where I hide my source codez
/project/src/Project.sln
/project/src/Project/Project.csproj
/project/src/Project/Directory.Build.props      # keeps a docker mapped volume from overwriting .dlls on your host
/project/src/Project.Data/Project.Data.csproj   # typical .Net project structure
/web-api                                        # another application...

Directory.Build.props (put this in the same folder as your .csproj, keeps your dotnet watch run command from messing with the source directory on your host)

<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>

run.yml (docker-compose.yml for debugging)

version: "3.5"
services:
  project:
    build:
      context: ./project
      dockerfile: run.Dockerfile
    ports:
      - 5000:80
    volumes:
      - ./project/src/Project:/app

run.Dockerfile (the Dockerfile for debugging)

FROM microsoft/dotnet:2.1-sdk

# install the .net core debugger
RUN apt-get update
RUN apt-get -y --no-install-recommends install unzip
RUN apt-get -y --no-install-recommends install procps
RUN rm -rf /var/lib/apt/lists/*

RUN curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg

VOLUME /app
WORKDIR /app

CMD dotnet watch run --urls http://0.0.0.0:80

build.yml (the docker-compose.yml for building release versions)

version: "3.5"
services:
  project:
    build:
      context: ./project
      dockerfile: build.Dockerfile
    volumes:
      - ./project:/app

build.Dockerfile (the Dockerfile for building release versions)

FROM microsoft/dotnet:2.1-sdk

VOLUME /app

# restore as a separate layer to speed up builds
WORKDIR /src
COPY src/Project/Project.csproj .
RUN dotnet restore

COPY src/Project/ .
CMD dotnet publish -c Release -o /app/out/

Solution 2

There's a simple solution, add the following two lines into your docker-compose.yml file, and the error will disappear.

    environment:
      - ASPNETCORE_URLS=https://+;http://+;

Solution 3

Just wanted to share one other issue I ran recently while containerizing a set of projects even if everything is configured correctly. Hope might help someone else.

Very inconspicuous but some of projects had in Program.cs:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();
    ...

Which removes all of the sources and ChainedConfigurationSource specifically that leads to the error above.

Solution 4

I solved the same issue in the following way:

  1. Added the following in appsettings.json to force Kestrel to listen to port 80.
"Kestrel": {
  "EndPoints": {
    "Http": {
      "Url": "http://+:80"
    }
  }
}
  1. Exposed the port in dockerfile
ENV ASPNETCORE_URLS=http://+:80

EXPOSE 80
  1. Ran the container using the below command.
docker run -p 8080:80 <image-name>:<tag>
  1. The app exposed on http://localhost:8080/
Share:
20,650
Mike Hawkins
Author by

Mike Hawkins

Updated on June 25, 2021

Comments

  • Mike Hawkins
    Mike Hawkins almost 3 years

    As the title indicates, i have a container that is unable to bind from host port to container port. I tried searching for similar issues, but have not found any related to using dotnet watch in a docker container since Microsoft introduced the microsoft/dotnet docker repo with dotnet watch built into the sdk image.

    Any suggestions as to what i am doing wrong are much appreciated.

    Dockerfile

    FROM microsoft/dotnet:2.1.301-sdk as build
    ENV DOTNET_USE_POLLING_FILE_WATCHER 1
    WORKDIR /app
    COPY . .
    RUN dotnet restore
    EXPOSE 5000-5001
    ENTRYPOINT [ "dotnet", "watch", "run", "--no-restore"]
    

    docker-compose.yml

    version: "3"
    
    services:
    
      esportapp:
        container_name: esportapp
        image: esportapp:dev
        build:
          context: .
          dockerfile: Docker/dev.Dockerfile
        volumes:
          - esportapp.volume:/app
        ports:
          - "5000:5000"
          - "5001:5001"
    
    volumes:
      esportapp.volume:
    

    Complete error:

    esportapp    | Hosting environment: Development
    esportapp    | Content root path: /app
    esportapp    | Now listening on: https://localhost:5001
    esportapp    | Now listening on: http://localhost:5000
    esportapp    | Application started. Press Ctrl+C to shut down.
    esportapp    | warn: Microsoft.AspNetCore.Server.Kestrel[0]
    esportapp    |       Unable to bind to https://localhost:5001 on the IPv6 loopback interface: 'Cannot assign requested address'.
    esportapp    | warn: Microsoft.AspNetCore.Server.Kestrel[0]
    esportapp    |       Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'.