Asked  7 Months ago    Answers:  5   Viewed   54 times

Is there a command I can run to get the container's IP address right from the host after a new container is created?

Basically, once Docker creates the container, I want to roll my own code deployment and container configuration scripts.

 Answers

95

The --format option of inspect comes to the rescue.

Modern Docker client syntax is:

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id

Old Docker client syntax is:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id

These commands will return the Docker container's IP address.

As mentioned in the comments: if you are on Windows, use double quotes " instead of single quotes ' around the curly braces.

Tuesday, June 1, 2021
 
diegoiglesias
answered 7 Months ago
77

You should use netifaces. It is designed to be cross-platform and contains specialised code for Windows together with a variety of generic versions that work on different UNIX/UNIX-like platforms.

As of netifaces version 0.10.0, Python3 is supported.

Usage Summary

>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
>>> ni.interfaces()
['lo', 'eth0', 'eth1', 'vboxnet0', 'dummy1']
>>>
>>> ni.ifaddresses('eth0')[AF_LINK]   # NOTE: AF_LINK is an alias for AF_PACKET
[{'broadcast': 'ff:ff:ff:ff:ff:ff', 'addr': '00:02:55:7b:b2:f6'}]
>>> ni.ifaddresses('eth0')[AF_INET]
[{'broadcast': '172.16.161.7', 'netmask': '255.255.255.248', 'addr': '172.16.161.6'}]
>>>
>>> # eth0 ipv4 interface address
>>> ni.ifaddresses('eth0')[AF_INET][0]['addr']
'172.16.161.6'
>>>>

Details

Windows Support:

No compiler required for most MS Windows installs. If you get warnings about installing MS Visual C++ for Windows, be very careful because you need to match the version of compiler used for your python with that used for the module.

Detailed example of netifaces data structures:

>>> import netifaces as ni
>>> ni.interfaces()
['lo', 'eth0', 'eth1', 'vboxnet0', 'dummy1']
>>> ni.ifaddresses('eth0')
{
    17: [
        {
            'broadcast': 'ff:ff:ff:ff:ff:ff',
            'addr': '00:02:55:7b:b2:f6'
        }
    ],
    2: [
        {
            'broadcast': '172.16.161.7',
            'netmask': '255.255.255.248',
            'addr': '172.16.161.6'
        }
    ],
    10: [
        {
            'netmask': 'ffff:ffff:ffff:ffff::',
            'addr': 'fe80::202:55ff:fe7b:b2f6%eth0'
        }
    ]
}
>>> 
>>> print(ni.ifaddresses.__doc__)
Obtain information about the specified network interface.

Returns a dict whose keys are equal to the address family constants,
e.g. netifaces.AF_INET, and whose values are a list of addresses in
that family that are attached to the network interface.
>>>
>>> # for the IPv4 address of eth0
>>> ni.ifaddresses('eth0')[2][0]['addr']
'172.16.161.6'

The numbers used to index protocols are from /usr/include/linux/socket.h (in Linux)... EDIT: my 3.2 kernel has them here: /usr/src/linux-headers-3.2.0-4-common/include/linux/socket.h

#define AF_INET         2       /* Internet IP Protocol         */
#define AF_INET6        10      /* IP version 6                 */
#define AF_PACKET       17      /* Packet family                */

The good news is that you don't have to remember all those header constants, they are included with netifaces:

>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
Sunday, June 13, 2021
 
StampyCode
answered 6 Months ago
65

The docker version is 1.10.1. I want the docker container to have same ip as the host with ports exposed.

When you use --net=host it tells the container to use the hosts networking stack. So you can't expose ports to the host, because it is the host (as far as the network stack is concerned).

docker inspect might not show the expose ports, but if you have an application listening on a port, it will be available as if it were running on the host.

Thursday, July 22, 2021
 
elias
answered 5 Months ago
77

You must set a container’s main process to bind to the special 0.0.0.0 “all interfaces” address, or it will be unreachable from outside the container.

In Docker 127.0.0.1 almost always means “this container”, not “this machine”. If you make an outbound connection to 127.0.0.1 from a container it will return to the same container; if you bind a server to 127.0.0.1 it will not accept connections from outside.


One of the core things Docker does is to give each container its own separate network space. In particular, each container has its own lo interface and its own notion of localhost.

At a very low level, network services call the bind(2) system call to start accepting connections. That takes an address parameter. It can be one of two things: either it can be the IP address of some system interface, or it can be the special 0.0.0.0 “all interfaces” address. If you pick an interface, it will only accept connections from that interface; if you have two network cards on a physical system, for example, you can use this to only accept connections from one network but not the other.

So, if you set a service to bind to 127.0.0.1, that’s the address of the lo interface, and the service will only accept connections from that interface. But each container has its own lo interface and its own localhost, so this setting causes the service to refuse connections unless they’re initiated from within the container itself. It you set it to bind to 0.0.0.0, it will also accept connections from the per-container eth0 interface, where all connections from outside the container arrive.

Saturday, August 14, 2021
 
iteong
answered 4 Months ago
37

You've asked for a dead container.

TL;DR: This is how to create a dead container

Don't do this at home:

ID=$(docker run --name dead-experiment -d -t alpine sh)
docker kill dead-experiment
test "$ID" != "" && chattr +i -R /var/lib/docker/containers/$ID
docker rm -f dead-experiment

And voila, docker could not delete the container root directory, so it falls to a status=dead:

docker ps -a -f status=dead
CONTAINER ID        IMAGE         COMMAND       CREATED             STATUS        PORTS         NAMES
616c2e79b75a        alpine        "sh"          6 minutes ago       Dead                        dead-experiment

Explanation

I've inspected the source code of docker and saw this state transition:

container.SetDead()
// (...)
if err := system.EnsureRemoveAll(container.Root); err != nil {
    return errors.Wrapf(err, "unable to remove filesystem for %s", container.ID)
}
// (...)
container.SetRemoved()

So, if docker cannot remove the container root directory, it remain as dead and does not continue to the Removed state. So I've forced the file permissions to not permit root remove files (chattr -i).

PS: to revert the directory permissions do this: chattr -i -R /var/lib/docker/containers/$ID

Monday, October 18, 2021
 
Rumata
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share