Connecting containers to networks

While having the ability to create your own networks is a huge leap forward, it means nothing without a means to connect containers to it. In previous versions of Docker, this was traditionally done during container runtime by passing the --net flag specifying which network the container should use. While this is certainly still the case, the docker network subcommand also allows you to connect and disconnect running containers to existing networks.

Getting ready

The docker network subcommand was introduced in Docker 1.9, so you'll need a Docker host running at least that version. In our examples, we'll be using Docker version 1.12. You'll also want to have a good understanding of your current network layout, so you can follow along as we inspect the current configuration. It is assumed that each Docker host is in its native configuration.

How to do it…

Connecting and disconnecting containers is done via the network connect and network disconnect subcommands:

user@docker1:~$ docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
Connects a container to a network
  --alias=[]         Add network-scoped alias for the container
  --help             Print usage
  --ip               IP Address
  --ip6              IPv6 Address
  --link=[]          Add link to another container
user@docker1:~$

Let's review what our options are for connecting containers to networks:

  • Alias: This allows you to define an alias for container name resolution in the network you are connecting the container to. We'll talk more about this in Chapter 5, Container Linking and Docker DNS, where we discuss DNS and linking.
  • IP: This defines an IP address to be used for the container. This will work so long as the IP address is not currently in use. Once allocated, it will remain reserved as long as the container is running or paused. Stopping the container will remove the reservation.
  • IP6: This defines an IPv6 address to be used for the container. The same allocation and reservation requirements that applied to the IPv4 address also apply to the IPv6 address.
  • Link: This allows you to specify a link to another container. We'll talk more about this in Chapter 5, Container Linking and Docker DNS, where we discuss DNS and linking.

Once a network connect request is sent, Docker handles all the configuration required in order for the container to start using the new interface. Let's take a look at a quick example:

user@docker1:~$ docker run --name web1 -d jonlangemak/web_server_1
e112a2ab8197ec70c5ee49161613f2244f4353359b27643f28a18be47698bf59
user@docker1:~$
user@docker1:~$ docker exec web1 ip addr
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
8: eth0@if9: <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
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
user@docker1:~$

In the above output we started a simple container without specifying any network-related configuration. The result is the container being mapped to the docker0 bridge. Now let's try connecting this container to the network we created in the previous recipe, mynetwork:

user@docker1:~$ docker network connect mynetwork web1
user@docker1:~$
user@docker1:~$ docker exec web1 ip addr
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
8: eth0@if9: <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
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
10: eth1@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link
       valid_lft forever preferred_lft forever
user@docker1:~$

As you can see, the container now has an IP interface on the network mynetwork. If we now once again inspect the network, we should see a container association:

user@docker1:~$ docker network inspect mynetwork
[
    {
        "Name": "mynetwork",
        "Id": "a09b7617c5504d4afd80c26b82587000c64046f1483de604c51fa4ba53463b50",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1/16"
                }
            ]
        },
        "Internal": false,
        "Containers": {           "e112a2ab8197ec70c5ee49161613f2244f4353359b27643f28a18be47698bf59": {
                "Name": "web1",
                "EndpointID": "678b07162dc958599bf7d463da81a4c031229028ebcecb1af37ee7d448b54e3d",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
user@docker1:~$

Networks can be disconnected just as easily. For instance, we can now remove the container from the docker0 bridge by removing it from the bridge network:

user@docker1:~$ docker network disconnect bridge web1
user@docker1:~$
user@docker1:~$ docker exec web1 ip addr
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
10: eth1@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link
       valid_lft forever preferred_lft forever
user@docker1:~$

It's interesting to point out that Docker also takes care of ensuring container connectivity when you connect and disconnect networks from the containers. For instance, before disconnecting the container from the bridge network, the default Gateway of the container was still out of the docker0 bridge:

user@docker1:~$ docker exec web1 ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth2  proto kernel  scope link  src 172.17.0.2
172.18.0.0/16 dev eth1  proto kernel  scope link  src 172.18.0.2
user@docker1:~$

This makes sense as we wouldn't want to interrupt container connectivity while connecting the container to a new network. However, once we remove the network hosting the default gateway by disconnecting the interface to the bridge network, we see that Docker updates the default gateway to the remaining interface out of the mynetwork bridge:

user@docker1:~$ docker exec web1 ip route
default via 172.18.0.1 dev eth1
172.18.0.0/16 dev eth1  proto kernel  scope link  src 172.18.0.2
user@docker1:~$

This ensures that the container has connectivity regardless of which network it's connected to.

Finally, I want to point out an interesting aspect of the none network type when you are connecting and disconnecting containers to networks. As I mentioned earlier, the none network type tells Docker to not assign the container to any networks. This however, does not mean just initially, it's a configuration state telling Docker that the container should not have any networks associated with it. For instance, assume we start the following container with a network of none:

user@docker1:~$ docker run --net=none --name web1 -d jonlangemak/web_server_1
9f5d73c55ee859335cd2449b058b68354f5b71cf37e57b72f5c984afcafb4b21
user@docker1:~$ docker exec web1 ip addr
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
user@docker1:~$

As you can see, the container doesn't have any network interfaces besides its loopback. Now, let's try and connect this container to a new network:

user@docker1:~$ docker network connect mynetwork web1
Error response from daemon: Container cannot be connected to multiple networks with one of the networks in private (none) mode
user@docker1:~$

Docker is telling us that this container was defined to have no networks and is preventing us from connecting the container to any network. If we inspect the none network, we can see that this container is in fact attached to it:

user@docker1:~$ docker network inspect none
[
    {
        "Name": "none",
        "Id": "a191c26b7dad643ca77fe6548c2480b1644a86dcc95cde0c09c6033d4eaff7f2",
        "Scope": "local",
        "Driver": "null",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Containers": {            "931a0d7ad9244c135a19de6e23de314698112ccd00bc3856f4fab9b8cb241e60": {
                "Name": "web1",
                "EndpointID": "6a046449576e0e0a1e8fd828daa7028bacba8de335954bff2c6b21e01c78baf8",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
user@docker1:~$

In order to connect this container to a new network, we first have to disconnect it from the none network:

user@docker1:~$ docker network disconnect none web1
user@docker1:~$ docker network connect mynetwork web1
user@docker1:~$ docker exec web1 ip addr
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link
       valid_lft forever preferred_lft forever
user@docker1:~$

Once you disconnect it from the none network, you are free to connect it to any other defined network.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset