Search code examples
dockerasp.net-coreconsul

Get Docker container IP within a .net core application


What is the best way to get the current docker container IP address within the container itself using .net core?

I try to register my container to a Consul server which is hosted on the Docker host (not as a container) and I need to get the container IP address on startup to make the registration. Because the IP addresses change on any container startup I can't just hard-code it into the appsettings.json. I followed this tutorial. And when it comes to this section:

// 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" }
};

The received address contains only the loopback address and not the actual container address (as seen from outside - the host where Consul is running). I already tried to use the HttpContext (which is null in the startup class) and the IHttpContextAccessor which also does not contain anything at this time.


EDIT: This is a part of my 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" ]
  }

The Uri is the one from my host system and I managed to register the service in Consul. The missing part is the <CONTAINER_IP/DNS> which is needed for Consul to perform some checks for that particular container. Here I need either the IP of the container or the DNS on which it is accessible from the host system. I know that this IP will switch with every container starup and it's in the settings only for demonstration purpose (I'm happy if I can get the IP at startup time).


Solution

  • Ok, I got it working and it was much easier than I thought.

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

    With the container_id/name I could get the IP with an easy compare if it's an IP4 address. I then can use this address and pass it to Consul. The health checks can now successfully call the container with it's IP from the outside host.

    I'm still not 100% satisfied with the result because it relies on the "first" valid IP4 address in the AddressList (currently, there are no more so I got this going for me). Any better / more generic solution would still be welcome.