【问题标题】:Get Docker container IP within a .net core application在 .net 核心应用程序中获取 Docker 容器 IP
【发布时间】:2019-01-26 06:42:43
【问题描述】:

使用.net core 在容器本身中获取当前 docker 容器 IP 地址的最佳方法是什么?

我尝试将我的容器注册到托管在 Docker 主机(而不是容器)上的 Consul 服务器,并且我需要在启动时获取容器 IP 地址以进行注册。因为任何容器启动时 IP 地址都会发生变化,所以我不能将其硬编码到 appsettings.json 中。我关注了这个tutorial。说到本节:

// Get server IP address
var features = app.Properties["server.Features"] as FeatureCollection;
var addresses = features.Get<IServerAddressesFeature>();
var address = addresses.Addresses.First();

// Register service with consul
var uri = new Uri(address);
var registration = new AgentServiceRegistration()
{
     ID = $"{consulConfig.Value.ServiceID}-{uri.Port}",
     Name = consulConfig.Value.ServiceName,
     Address = $"{uri.Scheme}://{uri.Host}",
     Port = uri.Port,
     Tags = new[] { "Students", "Courses", "School" }
};

收到的address 仅包含环回地址,而不包含实际的容器地址(从外部看 - 运行Consul 的主机)。我已经尝试使用HttpContext(即启动类中的null)和IHttpContextAccessor,此时也没有包含任何内容。


编辑:这是我appsettings.json的一部分:

  "ServiceRegistry": {
    "Uri": "http://172.28.112.1:8500",
    "Name": "AuthServiceApi",
    "Id": "auth-service-api-v1",
    "ContainerAddress": "http://<CONTAINER_IP/DNS>",
    "Checks": [
      {
        "Service": "/health",
        "Timeout": 5,
        "Interval":  10 
      }
    ], 
    "Tags": [ "Auth", "User" ]
  }

Uri 来自我的主机系统,我设法在 Consul 中注册了该服务。缺少的部分是 &lt;CONTAINER_IP/DNS&gt;,Consul 需要它来对该特定容器执行一些检查。在这里,我需要容器的 IP 或可以从主机系统访问它的 DNS。我知道这个 IP 会随着每次容器启动而切换,并且它在设置中仅用于演示目的(如果我能在启动时获得 IP,我很高兴)。

【问题讨论】:

  • 请问您为什么不喜欢使用 docker 主机名?这样,您根本不必担心内部 IP 地址,因为 docker 充当 DHCP 服务器,并且(默认情况下)容器的主机名就是它的名称。所以containername 将带您进入在 docker 中运行的容器之一
  • 您还应该遍历addresses.Addresses 属性。你只是选第一个,可能还有其他更合适的
  • @Tseng:我是否也可以使用它的 container_id 作为主机名,因为我在 docker-compose 中设置了 container_name 并且还使用了副本(完全不确定这将如何协同工作)?我对 docker 很陌生,不知道有这样的方法。我很欣赏其他不依赖 IP 的解决方案 :-)
  • 另外请记住,在 Docker Compose 上下文中,Compose 会告诉 Docker 每个容器可以通过其在 docker-compose.yml 文件中的键访问,这将不同于容器名称或容器私有主机名.

标签: docker asp.net-core consul


【解决方案1】:

我也有上面的要求,我必须启动一个 docker 容器并获取容器 IP 地址并保存到某个目录,所有这些都使用 c#(.net core) (这个概念也适用于其他编程语言) .下面是实现这一目标的一段代码。喜欢就点个赞吧,不喜欢就点个赞吧。

注意:此方法非常可靠,因为它会获取您想要的特定容器的 IP 地址。

static void Main(string[] args)
        {
          Console.WriteLine("Getting Container IP...");
          //This command returns back ip address of the required container.
          string inspectCommand = string.Concat("inspect -f ", "\"{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}\"", " container ID/Name");
          //The command is appended with string 'docker' as all docker commans starts with it
          var processInfo = new ProcessStartInfo("docker", $"{inspectCommand}");

          processInfo.CreateNoWindow = true;
          processInfo.UseShellExecute = false;
          processInfo.RedirectStandardOutput = true;
          processInfo.RedirectStandardError = true;'

          using (var process = new Process())
          {
            process.StartInfo = processInfo;
            var started = process.Start();

              StreamReader reader = process.StandardOutput;
              //to remove any unwanted char if appended 
              ip = Regex.Replace(reader.ReadToEnd(), @"\t|\n|\r", "");
              if(string.IsNullOrEmpty(ip))
              {
                Console.WriteLine($"Unable to get ip of the container");
                Environment.Exit(1);
              }
              Console.WriteLine($"Azurite conatainer is listening @ {ip}");

              Environment.Exit(1);
           }}

【讨论】:

  • 这会从容器外部获取容器IP。原始问题询问如何从容器inside获取容器IP。
  • @x0n 如果您阅读原始问题,它会说如何在 .net 核心应用程序中获取正在运行的容器 IP。所以我的解决方案就是这样做的。请在放弃之前正确阅读代码
  • 我确实读过它——我认为这是一个语言/上下文问题。 OP 想从 same 容器内运行的代码中了解容器 IP;他们接受的答案证明了这一点(仅适用于同一容器内)。您的方法正在调用 docker inspect,它在容器内不可用。我投了反对票,因为您的回答没有回答问题。
【解决方案2】:

好的,我得到了它,它比我想象的要容易得多。

var name = Dns.GetHostName(); // get container id
var ip = Dns.GetHostEntry(name).AddressList.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork);

使用container_id/name,如果它是IP4 地址,我可以通过简单的比较来获得IP。然后我可以使用这个地址并将其传递给 Consul。运行状况检查现在可以使用其 IP 从外部主机成功调用容器。

我仍然对结果不是 100% 满意,因为它依赖于 AddressList 中的“第一个”有效 IP4 地址(目前没有更多的,所以我得到了这个)。任何更好/更通用的解决方案仍然受到欢迎。

【讨论】:

  • 您好,您可以发布您的代码吗? ..你在哪里设置你的var ip?你在这里用吗? var registration = new AgentServiceRegistration() { ID = _registrationID, Name = _consulConfig.Value.ServiceName, Address = $"{uri.Host}", //
  • 我赞成你的回答,因为它以正确的方式给了我..但是请..需要更多帮助;)
  • @federicoscamuzzi:明天我会回答你。不在城里,也不能访问我的回购 atm。
  • 我已经完成了!!..现在我正在尝试将它部署在 k8 上..真的非常感谢您的帮助!!
  • 获取 pod IP 地址最可靠的方法是询问 k8s 本身。您可以在容器规范中添加一个 env var 并读取应用程序中的值 kubernetes.io/docs/tasks/inject-data-application/…
猜你喜欢
  • 2020-11-21
  • 2021-01-30
  • 1970-01-01
  • 2020-02-09
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2020-02-01
相关资源
最近更新 更多