I'm on Windows 11, and I want to retrieve the exposed ports of the currently running ASP.NET Core MVC linux image.
I tried using the InspectContainerAsync
method from the Docker.DotNet library, but it throws a System.Net.Http.HttpRequestException: 'Connection failed' error."
System.Net.Http.HttpRequestException: 'Connection failed'
SocketException: Cannot assign requested address
public static async Task<List<int>> GetExposedPorts()
{
var portsList = new List<int>();
var dockerClient = new DockerClientConfiguration(new Uri("unix:///var/run/docker.sock")).CreateClient();
var dockerId = GetDockerId();
var containerInspect = await dockerClient.Containers.InspectContainerAsync(dockerId);
foreach (var port in containerInspect.NetworkSettings.Ports)
portsList.Add(int.Parse(port.Key));
return portsList;
}
static string GetDockerId()
{
var containerId = string.Empty;
string cgroupFile = "/proc/self/cgroup";
if (System.IO.File.Exists(cgroupFile))
{
string[] lines = System.IO.File.ReadAllLines(cgroupFile);
foreach (string line in lines)
{
if (line.Contains("docker"))
{
string[] parts = line.Split('/');
containerId = parts[^1];
}
}
}
return containerId;
}
The GetDockerId method returns the correct Docker ID, but I still can't inspect the container. The URI seems correct, as I'm using a Linux container image.
Here are the steps to reproduce: In Visual Studio 2022, create a new MVC 8.0 project. Enable container support. Set the container OS to Linux. Set the container build type to Dockerfile. In the Debug menu, select 'Container (Dockerfile).'
Run the code provided above.
I'm on Windows 11, and I want to retrieve the exposed ports of the currently running ASP.NET Core MVC linux image.
I tried using the InspectContainerAsync
method from the Docker.DotNet library, but it throws a System.Net.Http.HttpRequestException: 'Connection failed' error."
System.Net.Http.HttpRequestException: 'Connection failed'
SocketException: Cannot assign requested address
public static async Task<List<int>> GetExposedPorts()
{
var portsList = new List<int>();
var dockerClient = new DockerClientConfiguration(new Uri("unix:///var/run/docker.sock")).CreateClient();
var dockerId = GetDockerId();
var containerInspect = await dockerClient.Containers.InspectContainerAsync(dockerId);
foreach (var port in containerInspect.NetworkSettings.Ports)
portsList.Add(int.Parse(port.Key));
return portsList;
}
static string GetDockerId()
{
var containerId = string.Empty;
string cgroupFile = "/proc/self/cgroup";
if (System.IO.File.Exists(cgroupFile))
{
string[] lines = System.IO.File.ReadAllLines(cgroupFile);
foreach (string line in lines)
{
if (line.Contains("docker"))
{
string[] parts = line.Split('/');
containerId = parts[^1];
}
}
}
return containerId;
}
The GetDockerId method returns the correct Docker ID, but I still can't inspect the container. The URI seems correct, as I'm using a Linux container image.
Here are the steps to reproduce: In Visual Studio 2022, create a new MVC 8.0 project. Enable container support. Set the container OS to Linux. Set the container build type to Dockerfile. In the Debug menu, select 'Container (Dockerfile).'
Run the code provided above.
Share Improve this question edited Apr 2 at 11:53 msd asked Apr 1 at 11:32 msdmsd 911 silver badge9 bronze badges 6 | Show 1 more comment2 Answers
Reset to default 2First problem
I did some quick experimentation myself and also had the same problem to start with. The socket needs to be mounted on the container running the code. To bind the socket you need to edit your Properties/LaunchSettings.json
. Find the startup profile for "commandName": "Docker"
and add the following line to the json: "containerRunArguments": "-v /var/run/docker.sock:/var/run/docker.sock"
.
This can also be accomplised in Visual Studio UI by right-clicking the project, go to properties. Then in the left menu go to Debug
and within Debug
click on the Open debug launch profiles UI
link. This will popup a new window. In this window on the left side click your Dockerfile profile, scroll down to Container run arguments
and input -v /var/run/docker.sock:/var/run/docker.sock
.
Next problem; permission denied
After this initial problem, when running the code, you get a permission denied
error on the socket. After a bit of playing around, I found out that this was because the default container user of ASP.NET core (8+) images is run with the principle of least privilege.
To change this you can open your dockerfile and remove (or change to root) default 5th line (or second command); the one that states USER $APP_UID
.
Last problem; int.parse throws
Another problem I noticed while experimenting with your code is that it currently crashes after connecting to the socket. Because the portnumber strings are in format [portnumber]/[protocol]
for example: 8081/tcp
.
So another small change would be to account for this:
static async Task<List<int>> GetExposedPorts()
{
var portsList = new List<int>();
var dockerClient = new DockerClientConfiguration(new Uri("unix:///var/run/docker.sock")).CreateClient();
var dockerId = GetDockerId();
var containerInspect = await dockerClient.Containers.InspectContainerAsync(dockerId);
foreach (var port in containerInspect.NetworkSettings.Ports)
{
var portString = port.Key;
// Ports can be in format "8080/tcp" for example
if (portString.IndexOf('/') is int index && index > 0)
portString = portString.Substring(0, index);
if (int.TryParse(portString, out int portNumber))
portsList.Add(portNumber);
}
return portsList;
}
Based on your steps to reproduce, it is likely
1. Incorrect Docker API URI
2. Issue mounting the Docker socket
3. Container use permission issues
1. Make sure you are using the correct URI, it is unix:///var/run/docker.sock
for Linux and npipe:////./pipe/docker_engine
for Windows.
2. If you are using docker compose mount the file by adding this line to the docker-compose.yml or override:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Or run this when starting your container if not using compose:
docker run -v /var/run/docker.sock:/var/run/docker.sock my-image
3. Inside the container runs groups
. If docker
is missing from the output then update your Dockerfile and try again:
RUN groupadd -r docker && usermod -aG docker myuser
USER myuser
Or run the container as root:
docker run --user root -v /var/run/docker.sock:/var/run/docker.sock my-image
unix:
prefix suggests you're running this code on Linux. You'd neednpipe://./pipe/docker_engine"
on Windows, even if Docker used WSL underneath. This question doesn't seem to have anything to do with ASP.NET Core. You should be able to reproduce the problem with a Console application – Panagiotis Kanavos Commented Apr 2 at 6:57