Skip to content
Advertisement

How can I expose a port from ASP.NET Core in Docker linux container in Windows?

I have several ASP.NET Core services defined in docker-compose. I need to be able to expose port in the host network (I use linux containers on Docker for Windows 18.03.0-ce).

Sample:

  • Services C1 and C2 are running in containers.
  • Service H3 is running directly in the host, not in container.
  • All services (C1, C2 and H3) must be accesible to each other.

I don’t know how to setup networking for services C1 and C2 in docker-compose. I tried this:

version: '3'

services:
  c1:
    image: <some image name>
    build:
      context: .
      dockerfile: <path to dockerfile>
    environment:
      - ASPNETCORE_ENVIRONMENT=Development      
      - ASPNETCORE_URLS=http://localhost:9084
    ports:
      - "9084:9084"
    network_mode: "host"

  c2:
    image: <some image name>
    build:
      context: .
      dockerfile: <path to dockerfile>
    environment:
      - ASPNETCORE_ENVIRONMENT=Development      
      - ASPNETCORE_URLS=http://localhost:9085
    ports:
      - "9085:9085"
    network_mode: "host"

I see this in the console when containers are started:

Hosting environment: Development
Content root path: /app
Now listening on: http://localhost:9085
Application started. Press Ctrl+C to shut down.

But I cannot connect them from the host. netstat -an doesn’t show these ports, telnet localhost 9084 fails.

This is output from docker inspect for that container:

"NetworkSettings": {
    "Bridge": "",
    "SandboxID": "df480d4d68cb109dc6b85f689f8b210a9f74e650c48a343cdd3d11eb3d10bec7",
    "HairpinMode": false,
    "LinkLocalIPv6Address": "",
    "LinkLocalIPv6PrefixLen": 0,
    "Ports": {},
    "SandboxKey": "/var/run/docker/netns/default",
    "SecondaryIPAddresses": null,
    "SecondaryIPv6Addresses": null,
    "EndpointID": "",
    "Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "IPAddress": "",
    "IPPrefixLen": 0,
    "IPv6Gateway": "",
    "MacAddress": "",
    "Networks": {
        "host": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "NetworkID": "324d836f54fa685d56b416f01a18e3e75f88d4516dafac43bb1a4ff760a2b67a",
            "EndpointID": "9212f6a01e142ef9fb71116c9fe03c37567c60ed8a2add91fe28bf0bd6de001a",
            "Gateway": "",
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "",
            "DriverOpts": null
        }
    }
}

When I remove network_mode: "host" configuration from docker-compose (network is then bridge as default), I get this message form the application:

warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:9084 on the IPv6 loopback interface: 'Error -99 EADDRNOTAVAIL address not available'.

Can you help me to setup the network configuration?

Advertisement

Answer

I found a solution for my problem:

  • I do not set any network in docker-compose (the generated *_default with bridge driver is used) – removed network_mode.
  • I removed ASPNETCORE_URLS ENV variable in docker-compose.
  • APS.NET Core applications use port 80 (inside container).
  • Port 80 is exposed (for example) as 9084 to be accessible from the host.
  • Application is configured to use (for example) localhost:9085.
  • docker-compose uses environment variable to override the endpoint to host.docker.internal.9085.

Now, all services running in containers use host.docker.internal and some port to connect to some other service, so these services can connect other services running in a container or directly in the host.

Services running in the host use localhost and some port, so they can connect other services running in the host or in the container.

This is sample of docker-compose file:

version: '3'

services:
  c1:
    image: <some image name>
    build:
      context: .
      dockerfile: <path to dockerfile>
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    env_file:
      - docker-compose.override.env
    ports:
      - "9084:80"

  c2:
    image: <some image name>
    build:
      context: .
      dockerfile: <path to dockerfile>
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    env_file:
      - docker-compose.override.env
    ports:
      - "9085:80"

Sample of docker-compose.override.env file:

ApiOptions__DomainModelApiBaseUrl=http://host.docker.internal:9081/api
ApiOptions__SearchApiBaseUrl=http://host.docker.internal:9088/api

Now I am able to run the same service in container or from Visual Studio and debug it.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement