最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How can I get the exposed ports of a Docker container? - Stack Overflow

programmeradmin7浏览0评论

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
  • Removed ASP.NET related tags, as the sample code has nothing to do with them. Why did you add them in the first place? – Lex Li Commented Apr 2 at 1:03
  • Because I'm using the library in an ASP.NET project. – msd Commented Apr 2 at 2:22
  • If you write some code with Docker.DotNet to automate Docker operations and execute it in an ASP.NET web app, you should edit the question to clearly describe that, as well as related IIS configuration. Keep in mind the same code can run differently in console/desktop apps. Besides, ASP.NET and ASP.NET Core are different, so you need to reveal which one you use and its version number too. – Lex Li Commented Apr 2 at 4:08
  • Please add the full exception text and mention what OS is used. The unix: prefix suggests you're running this code on Linux. You'd need npipe://./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
  • I've updated the question. Are you able to reproduce the problem? I've tried different URIs (including npipe://./pipe/docker_engine) and disabled the firewall. I've also tried all the suggested solutions here: github/dotnet/Docker.DotNet/issues/220 – msd Commented Apr 2 at 7:22
 |  Show 1 more comment

2 Answers 2

Reset to default 2

First 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
发布评论

评论列表(0)

  1. 暂无评论