Introduction to Container Networking
By the end of this exercise, you should be able to:
- Create docker bridge networks and attach containers to them
- Design networks of containers that can successfully resolve each other via DNS and reach each other across a Docker software defined network.
Inspecting the Default Bridge
See what networks are present on your host:
[centos@node-1 ~]$ docker network lsYou should have entries for
host,none, andbridge.Find some metadata about the default
bridgenetwork:[centos@node-1 ~]$ docker network inspect bridgeNote especially the private subnet assigned by Docker's IPAM driver to this network. The first IP in this range is used as the network's gateway, and the rest will be assigned to containers as they join the network.
See similar info from common networking tools:
[centos@node-1 ~]$ ip addrNote the
bridgenetwork's gateway corresponds to the IP of thedocker0device in this list.docker0is the linux bridge itself, whilebridgeis the name of the default Docker network that uses that bridge.Use
brctlto see connections to thedocker0bridge:[centos@node-1 ~]$ brctl show docker0 bridge name bridge id STP enabled interfaces docker0 8000.02427f12c30b noAt the moment, there are no connections to
docker0.
Connecting Containers to docker0
Start a container and reexamine the network; the container is listed as connected to the network, with an IP assigned to it from the bridge network's subnet:
[centos@node-1 ~]$ docker container run --name u1 -dt centos:7 [centos@node-1 ~]$ docker network inspect bridge ... "Containers": { "11da9b7db065f971f78aebf14b706b0b85f07ec10dbf6f0773b1603f48697961": { "Name": "u1", "EndpointID": "670c4950816c43da255f44399d706fff3a7934831defce625f3ff8945000b1b0", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, ...Inspect the network interfaces with
ipandbrctlagain, now that you have a container running:[centos@node-1 ~]$ ip addr ... 5: veth6f244c3@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP link/ether aa:71:82:6c:f3:88 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::a871:82ff:fe6c:f388/64 scope link valid_lft forever preferred_lft forever [centos@node-1 ~]$ brctl show docker0 bridge name bridge id STP enabled interfaces docker0 8000.02427f12c30b no veth6f244c3ip addrindicates a veth endpoint has been created and plugged into thedocker0bridge, as indicated bymaster docker0, and that it is connected to device index 4 in this case (indicated by the@if4suffix to the veth device name above). Similarly,brctlnow shows this veth connection ondocker0(notice that the ID for the veth connection matches in both utilities).Launch a bash shell in your container, and look for the
eth0device therein:[centos@node-1 ~]$ docker container exec -it u1 bash [root@11da9b7db065 /]# yum install -y iproute [root@11da9b7db065 /]# ip addr ... 4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 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 foreverWe see that the
eth0device in this namespace is in fact the device that the veth connection in the host namespace indicated it was attached to, and vice versa -eth0@if5indicates it is plugged into networking interface number 5, which we saw above was the other end of the veth connection. Docker has created a veth connection with one end in the host'sdocker0bridge, and the other providing theeth0device in the container.
Defining Additional Bridge Networks
In the last step, we investigated the default bridge network; now let's try making our own. User defined bridge networks work exactly the same as the default one, but provide DNS lookup by container name, and are firewalled from other networks by default.
Create a bridge network by using the
bridgedriver withdocker network create:[centos@node-1 ~]$ docker network create --driver bridge my_bridgeLaunch a container connected to your new network via the
--networkflag:[centos@node-1 ~]$ docker container run --name=u2 --network=my_bridge -dt centos:7Use the
inspectcommand to investigate the network settings of this container:[centos@node-1 ~]$ docker container inspect u2my_bridgeshould be listed under theNetworkskey.Launch another container, this time interactively:
[centos@node-1 ~]$ docker container run --name=u3 --network=my_bridge -it centos:7From inside container
u3, pingu2by name:ping u2. The ping succeeds, since Docker is able to resolve container names when they are attached to a custom network.Try starting a container on the default network, and pinging
u1by name:[centos@node-1 ~]$ docker container run centos:7 ping u1 ping: u1: Name or service not knownThe ping fails; even though the containers are both attached to the
bridgenetwork, Docker does not provide name lookup on this default network. Try the same command again, but usingu1's IP instead of name, and you should be successful.Finally, try pinging
u1by IP, this time from containeru2:[centos@node-1 ~]$ docker container exec u2 ping <u1 IP>The ping fails, since the containers reside on different networks; all Docker networks are firewalled from each other by default.
Clean up your containers and networks:
[centos@node-1 ~]$ docker container rm -f $(docker container ls -aq) [centos@node-1 ~]$ docker network rm my_bridge
Conclusion
In this exercise, you explored the fundamentals of container networking. The key take away is that containers on separate networks are firewalled from each other by default. This should be leveraged as much as possible to harden your applications; if two containers don't need to talk to each other, put them on separate networks.
You also explored a number of API objects:
docker network lslists all networks on the hostdocker network inspect <network name>gives more detailed info about the named networkdocker network create --driver <driver> <network name>creates a new network using the specified driver; so far, we've only seen thebridgedriver, for creating a linux bridge based network.docker network connect <network name> <container name or id>connects the specified container to the specified network after the container is running; the--networkflag indocker container runachieves the same result at container launch.docker container inspect <container name or id>yields, among other things, information about the networks the specified container is connected to.