`dotnet run` fails with "address already in use" for fixed external ports via `.WithEndpoint`
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
💡 _Review of dotnet/docs-aspire#2340 clarifies the intended behavioral difference between "Run Mode" (which actively allocates ports) and "Publish Mode" (which only generates manifest expressions). While this explains why the failure only occurs during `dotnet run`, it does not address the core issue: the "address already in use" error occurs when the port is demonstrably free, which suggests a runtime allocation bug rather than a configuration error._
### Describe the bug
When an Aspire resource (e.g., Redis) is configured with a fixed external port using `.WithEndpoint(..., port: 6379, isExternal: true)`, running the application via `dotnet run` fails. The container (e.g., redisContainer) fails to start, and the logs show the error: `failed to set up container networking... failed to listen on TCP socket: address already in use.`
This behavior is specific to `dotnet run`. Running `aspire publish -p docker-compose` generates a valid `docker-compose.yml` file that maps the port correctly. Furthermore, if the `.WithEndpoint` call is removed, `dotnet run` succeeds, but maps the container to a random, non-deterministic host port.
The exact error message is
```
fail: Aspire.Hosting.Dcp.dcpctrl.dcpctrl.ContainerReconciler[0]
Failed to start Container {"Container": "/redisContainer", "Reconciliation": 7, "ContainerID": "f0d38d74eda3", "ContainerName": "redisContainer", "error": "status of container 'redisContainer' is 'created' (was expecting 'running'), error: failed to set up container networking: driver failed programming external connectivity on endpoint redisContainer (9062c8a9a0212fcc079440679b6df194dab9b5fbeb6710599f7a5b8f3e3c7b69): failed to listen on TCP socket: address already in use\ndocker command 'StartContainers' returned with non-zero exit code 1\nnot all requested objects were returned\nonly 0 out of 1 containers were successfully started"}
```
### Expected Behavior
The AppHost configuration should be applied consistently across all execution and publishing models. Given that `aspire publish -p docker-compose` correctly generates a functional `docker-compose.yml` file that maps the container's `targetPort` (6379) to the host `port` (6379), the `dotnet run` command is expected to apply the same port mapping and start the container successfully.
The "address already in use" error should not occur during `dotnet run` for a port defined via `.WithEndpoint(..., isExternal: true)`, assuming the specified host port is not already occupied by a separate, non-Aspire process.
### Steps To Reproduce
1. Use the code below.
2. Ensure no other applications on the host machine are using TCP port 6379.
3. Run the application from the command line: `dotnet run`.
5. Observe the application logs and note the `ContainerReconciler` failure with the "address already in use" error for the `redisContainer`.
```csharp
var builder = DistributedApplication.CreateBuilder(args);
var compose = builder.AddDockerComposeEnvironment("compose")
.WithProperties(env =>
{
env.DefaultNetworkName = "myNetwork";
env.BuildContainerImages = false;
})
.ConfigureComposeFile(file =>
{
file.Name = "myProject";
});
var redisPassword = builder.AddParameter("redis-password", secret: true);
var cache = builder.AddRedis("redisResource")
.WithContainerName("redisContainer")
.WithPassword(redisPassword)
.WithEndpoint(name: CustomEndpointName, targetPort: 6379, port: 6379, isExternal: true);
builder.Build().Run();
```
### Anything else?
Output of the `aspire publish -p docker-compose` generated `docker-compose.yml` which provided an expected output.
```yml
name: "myProject"
services:
compose-dashboard:
image: "mcr.microsoft.com/dotnet/nightly/aspire-dashboard:latest"
expose:
- "18888"
- "18889"
networks:
- "myNetwork"
restart: "always"
redisresource:
image: "docker.io/library/redis:8.2"
container_name: "redisContainer"
command:
- "-c"
- "redis-server --requirepass $$REDIS_PASSWORD"
entrypoint:
- "/bin/sh"
environment:
REDIS_PASSWORD: "${REDIS_PASSWORD}"
ports:
- "6379:6379"
expose:
- "6379"
networks:
- "myNetwork"
networks:
myNetwork:
driver: "bridge"
```
### Aspire Package References
```
```
### .NET Version info
output of `➜ dotnet --info`
```
.NET SDK:
Version: 9.0.306
Commit: cc9947ca66
Workload version: 9.0.300-manifests.59b597ef
MSBuild version: 17.14.28+09c1be848
Runtime Environment:
OS Name: Windows
OS Version: 10.0.26200
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.306\
.NET workloads installed:
[android]
Installation Source: SDK 9.0.300, VS 17.14.36603.0
Manifest Version: 35.0.101/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.android\35.0.101\WorkloadManifest.json
Install Type: Msi
[ios]
Installation Source: SDK 9.0.300, VS 17.14.36603.0
Manifest Version: 26.0.9752/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.ios\26.0.9752\WorkloadManifest.json
Install Type: Msi
[maccatalyst]
Installation Source: SDK 9.0.300, VS 17.14.36603.0
Manifest Version: 26.0.9752/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.maccatalyst\26.0.9752\WorkloadManifest.json
Install Type: Msi
[maui-windows]
Installation Source: SDK 9.0.300, VS 17.14.36603.0
Manifest Version: 9.0.111/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.maui\9.0.111\WorkloadManifest.json
Install Type: Msi
Configured to use loose manifests when installing new manifests.
Host:
Version: 9.0.10
Architecture: x64
Commit: e1f19886fe
.NET SDKs installed:
6.0.428 [C:\Program Files\dotnet\sdk]
9.0.306 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
```
Contributor guide
Assessment
This issue has not been assessed yet.