Exploring Docker Networking – Bridge

Exploring Docker Networking – Bridge

Back on the server side, we can do an inspect of the docker container as well as the network again to see some more info.  If you are new to Docker, creating a container without a name causes it to have a randomly generated and usually hilarious name, in our case here distracted_lamarr.

[root@dockernet ~]# docker container ls
CONTAINER ID IMAGE  COMMAND     CREATED           STATUS           PORTS  NAMES
98c3dbff6afc centos "/bin/bash" About an hour ago Up About an hour        distracted_lamarr
[root@dockernet ~]# docker inspect distracted_lamarr
[
 {
 "Id": "98c3dbff6afc63307fd699453d00e4039c8f4f2f1f1b52411088aa6f00e5ab05",
 "Created": "2017-07-24T21:37:27.371160948Z",
 "Path": "/bin/bash",

<...snip...>

"NetworkSettings": {
 "Bridge": "",
 "SandboxID": "3be322af84fc16b8bcef25cb5d2d6d28214f5a87e0307e1c08d8778330534d7e",
 "HairpinMode": false,
 "LinkLocalIPv6Address": "",
 "LinkLocalIPv6PrefixLen": 0,
 "Ports": {},
 "SandboxKey": "/var/run/docker/netns/3be322af84fc",
 "SecondaryIPAddresses": null,
 "SecondaryIPv6Addresses": null,
 "EndpointID": "e67748bb21d2abed1f74ebf4d44e378c6e7450436441f341e24c9b7321a099e4",
 "Gateway": "172.17.0.1",
 "GlobalIPv6Address": "",
 "GlobalIPv6PrefixLen": 0,
 "IPAddress": "172.17.0.2",
 "IPPrefixLen": 16,
 "IPv6Gateway": "",
 "MacAddress": "02:42:ac:11:00:02",
 "Networks": {
 "bridge": {
 "IPAMConfig": null,
 "Links": null,
 "Aliases": null,
 "NetworkID": "c7a2943b83359f7c22d57e0e01f4295b702b17ca3bb93130e566ac3f2992d493",
 "EndpointID": "e67748bb21d2abed1f74ebf4d44e378c6e7450436441f341e24c9b7321a099e4",
 "Gateway": "172.17.0.1",
 "IPAddress": "172.17.0.2",
 "IPPrefixLen": 16,
 "IPv6Gateway": "",
 "GlobalIPv6Address": "",
 "GlobalIPv6PrefixLen": 0,
 "MacAddress": "02:42:ac:11:00:02",
 "DriverOpts": null
 }
 }
 }
 }
]

 [root@dockernet ~]# docker network inspect bridge
<...snip...>
 "Containers": {
 "98c3dbff6afc63307fd699453d00e4039c8f4f2f1f1b52411088aa6f00e5ab05": {
 "Name": "distracted_lamarr",
 "EndpointID": "e67748bb21d2abed1f74ebf4d44e378c6e7450436441f341e24c9b7321a099e4",
 "MacAddress": "02:42:ac:11:00:02",
 "IPv4Address": "172.17.0.2/16",
 "IPv6Address": ""
 }

So a lot of good info here.  I’ve highlighted some things which you can verify, like the IP and MAC address which were automatically assigned.  The docker inspect command can help you find a ton of great info.

Notice one thing I highlighted which is the SandboxKey.  This will answer our question of where the network devices went and how they are tied together.  Linux uses network namespaces to essentially segment things out logically.  So your container uses a different network namespace (which Docker calls a sandbox) than the server, hence we don’t see the interfaces of one in the other.  And in fact, veth interfaces are designed to span separate network namespaces.

How can we see the network namespace, or even know that it is a real thing?  Great question!  It is actually not very straightforward.  Normally network namespaces are defined in /var/run/netns which is where the command to view them (ip netns list) looks for them.  Unfortunately as you can see, Docker stores them in a separate place (/var/run/docker/netns).  In my case because this is just a dummy test system, I can fix this easily by softlinking /var/run/netns to the docker location.  Personally I wouldn’t do this in a real system but this is what testing is for!

[root@dockernet ~]# ip netns list
[root@dockernet ~]# ln -s /var/run/docker/netns/ /var/run/netns
[root@dockernet ~]# ip netns list
3be322af84fc (id: 0)

Here after I’ve linked the network namespace to the proper location, my command returns something.  We can see the network namespace id is 0 which also happens to be the link-netnsid value from ip addr show.  We can also see that the name is 3be322af84fc which matches up properly from the docker inspect information.

Now that we know the namespace and have the linking, I can actually exec against that namespace and verify that we are looking at the right thing.

[root@dockernet ~]# ip netns exec 3be322af84fc ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
 link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
 inet 172.17.0.2/16 scope global eth0
 valid_lft forever preferred_lft forever

Recall that this is the same output from the container, but this is executed from the server using the ip netns exec command.

Finally (almost done!) I’ll show some diagrams and show you a few more interesting things before closing out.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s