Application running in a Podman container within WSL 2 cannot connect to a service running on the Windows host.
I have got the following minimalistic setup:
podman --rm -it alpine sh
. Then curl was installed by command apk add curl
The container belongs to the default bridge
network.
[
{
"name": "podman",
"id": "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
"driver": "bridge",
"network_interface": "podman0",
"created": "2024-10-17T15:56:07.008133925+02:00",
"subnets": [
{
"subnet": "10.88.0.0/16",
"gateway": "10.88.0.1"
}
],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": false,
"ipam_options": {
"driver": "host-local"
},
"containers": {
"2f61f8752f703ac1ca87109713928b7861bfe4fd09fa2f1afd24fea08d37fde0": {
"name": "stupefied_davinci",
"interfaces": {
"eth0": {
"subnets": [
{
"ipnet": "10.88.0.6/16",
"gateway": "10.88.0.1"
}
],
"mac_address": "fe:c9:60:df:2d:14"
}
}
}
}
}
]
The issue is, I cannot reach the web app running on the Windows machine from the podman container. Whenever I try to call curl http://host.containers.internal/weatherforecast
(from within the container) I get the error curl: (7) Failed to connect to host.docker.internal port 80 after 0 ms: Could not connect to server
.
Yet I am able to access the web app from the Windows machine without any issues. I am also able to access internet from within the Podman container.
host.docker.internal
The funny thing is, the very same setup works with Docker. It is only Podman that is having some issues (for no apparent reason). Unfortunately, I have to go with Podman - company policy.
Well, it turns out, Podman is not as smart in domain name resolution as Docker. Despite Podman is supposed to route the domain host.containers.internal
to the host machine, this does not seem to be automatic (at least not on Windows).
There seem to be a few ways to solve the problem - I decided to go for Solution 2.
Add an extra host to the container when starting the container.
Get-NetIpAddress | where { $_.InterfaceAlias -Like '*WSL*' -and $_.AddressFamily -EQ "IPv4" } |select -ExpandProperty IPAddress
--add-host
argument - however replace the IP address (172.22.208.1 is just an example) with the IP address from step 2:podman run --add-host=host.containers.internal:172.22.208.1 --rm -it alpine sh
Add an extra host to the container when starting the container but the host IP address is taken from a config file (/etc/containers/containers.conf
) on the Podman Linux machine (podman-machine-default).
Get-NetIpAddress | where { $_.InterfaceAlias -Like '*WSL*' -and $_.AddressFamily -EQ "IPv4" } |select -ExpandProperty IPAddress
wsl --distribution podman-machine-default
/etc/containers/containers.conf
under the [containers]
section - however replace the IP address (172.22.208.1
is just an example) with the IP address from step 2:host_containers_internal_ip = "172.22.208.1"
CTRL+D
twice.podman machine stop
podman machine start
--add-host=host.containers.internal:host-gateway
argument:podman run --add-host=host.containers.internal:host-gateway --rm -it alpine sh
This time, the extra host points to the IP defined in host_containers_internal_ip
from containers.conf
.
(This solution worked for some cases but NOT always.)
Manually adjust hosts configuration of the WSL2 instance of the Podman Linux machine (podman-machine-default). In order to do so, follow these steps:
Get-NetIpAddress | where { $_.InterfaceAlias -Like '*WSL*' -and $_.AddressFamily -EQ "IPv4" } |select -ExpandProperty IPAddress
wsl --distribution podman-machine-default
/etc/wsl.conf
so the /etc/hosts
file won't be auto-generated by Windows anymore:[network]
generateHosts = false
/etc/hosts
- however replace the IP address (172.22.208.1
is just an example) with the IP address from step 2:172.22.208.1 host.containers.internal
Now it is possible to call services running on the Windows machine from container by using the domain name host.containers.internal
.
Visual Studio uses some clever tricks to make debugging of containerized .NET applications fast. Also Visual Studio starts the container automatically when debugging. Therefore we need to set up MSBuild so it uses the extra argument --add-host=host.containers.internal:host-gateway
(from Solution 2) when starting the container.
In order to achieve that, add a property to the corresponding csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<DockerfileRunArguments>--add-host=host.containers.internal:host-gateway</DockerfileRunArguments>
</PropertyGroup>
</Project>