diff --git a/engine/userguide/networking/work-with-networks.md b/engine/userguide/networking/work-with-networks.md index e3f18cff67..e863e1ddc2 100644 --- a/engine/userguide/networking/work-with-networks.md +++ b/engine/userguide/networking/work-with-networks.md @@ -73,10 +73,6 @@ The `dockerd` options that support the `overlay` network are: * `--cluster-store-opt` * `--cluster-advertise` -It is also a good idea, though not required, that you install Docker Swarm -to manage the cluster. Swarm provides sophisticated discovery and server -management that can assist your implementation. - When you create a network, Engine creates a non-overlapping subnetwork for the network by default. You can override this default and specify a subnetwork directly using the `--subnet` option. On a `bridge` network you can only @@ -103,12 +99,11 @@ $ docker network create -d overlay \ my-multihost-network ``` -Be sure that your subnetworks do not overlap. If they do, the network create +Be sure that your subnetworks do not overlap. If they do, network creation fails and Engine returns an error. -When creating a custom network, the default network driver (i.e. `bridge`) has -additional options that can be passed. The following are those options and the -equivalent docker daemon flags used for docker0 bridge: +When creating a custom network, you can pass additional options to the driver. +The `bridge` driver accepts the following options: | Option | Equivalent | Description | |--------------------------------------------------|-------------|-------------------------------------------------------| @@ -127,7 +122,9 @@ The following arguments can be passed to `docker network create` for any network | `--internal` | - | Restricts external access to the network | | `--ipv6` | `--ipv6` | Enable IPv6 networking | -For example, now let's use `-o` or `--opt` options to specify an IP address binding when publishing ports: +The following example uses `-o` to bind to a specific IP address when binding +ports, then uses `docker network inspect` to inspect the network, and finally +attaches a new container to the new network. ```bash $ docker network create -o "com.docker.network.bridge.host_binding_ipv4"="172.23.0.1" my-network @@ -171,687 +168,839 @@ bafb0c808c53 redis "/entrypoint.sh redis" 4 seconds ago ## Connect containers -You can connect containers dynamically to one or more networks. These networks -can be backed the same or different network drivers. Once connected, the +You can connect an existing container to one or more networks. A container can +connect to networks which use different network drivers. Once connected, the containers can communicate using another container's IP address or name. For `overlay` networks or custom plugins that support multi-host connectivity, containers connected to the same multi-host network but launched from different hosts can also communicate in this way. -Create two containers for this example: +This example uses six containers, and directs you to create them as they are +needed. -```bash -$ docker run -itd --name=container1 busybox +### Basic container networking example -18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731 +1. First, create and run two containers, `container1` and `container2`: -$ docker run -itd --name=container2 busybox + ```bash + $ docker run -itd --name=container1 busybox -498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152 + 18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731 + + $ docker run -itd --name=container2 busybox + + 498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152 ``` -Then create an isolated, `bridge` network to test with. +2. Create an isolated, `bridge` network to test with. -```bash -$ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw + ```bash + $ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw -06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8 -``` + 06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8 + ``` -Connect `container2` to the network and then `inspect` the network to verify +3. Connect `container2` to the network and then `inspect` the network to verify the connection: -``` -$ docker network connect isolated_nw container2 + ```bash + $ docker network connect isolated_nw container2 -$ docker network inspect isolated_nw + $ docker network inspect isolated_nw -[ - { - "Name": "isolated_nw", - "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", - "Scope": "local", - "Driver": "bridge", - "IPAM": { - "Driver": "default", - "Config": [ - { - "Subnet": "172.25.0.0/16", - "Gateway": "172.25.0.1/16" + [ + { + "Name": "isolated_nw", + "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", + "Scope": "local", + "Driver": "bridge", + "IPAM": { + "Driver": "default", + "Config": [ + { + "Subnet": "172.25.0.0/16", + "Gateway": "172.25.0.1/16" + } + ] + }, + "Containers": { + "90e1f3ec71caf82ae776a827e0712a68a110a3f175954e5bd4222fd142ac9428": { + "Name": "container2", + "EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d", + "MacAddress": "02:42:ac:19:00:02", + "IPv4Address": "172.25.0.2/16", + "IPv6Address": "" } - ] - }, - "Containers": { - "90e1f3ec71caf82ae776a827e0712a68a110a3f175954e5bd4222fd142ac9428": { - "Name": "container2", - "EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d", - "MacAddress": "02:42:ac:19:00:02", - "IPv4Address": "172.25.0.2/16", - "IPv6Address": "" - } - }, - "Options": {} + }, + "Options": {} + } + ] + ``` + + Notice that `container2` is assigned an IP address automatically. Because + you specified a `--subnet` when creating the network, the IP address was + chosen from that subnet. + + As a reminder, `container1` is only connected to the default `bridge` network. + +4. Start a third container, but this time assign it an IP address using the + `--ip` flag and connect it to the `isolated_nw` network using the `docker run` + command's `--network` option: + + ```bash + $ docker run --network=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox + + 467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551 + ``` + + As long as the IP address you specify for the container is part of the + network's subnet, you can assign an IPv4 or IPv6 address to a container + when connecting it to a network, by using the `--ip` or `--ip6` flag. when + you specify an IP address in this way while using a user-defined network, + the configuration is preserved as part of the container's configuration and + will be applied when the container is reloaded. Assigned IP addresses are + preserved when using non-user-defined networks, because there is no guarantee + that a container's subnet will not change when the Docker daemon restarts unless + you use user-defined networks. + +5. Inspect the network resources used by `container3`. The + output below is truncated for brevity. + + ```bash + $ docker inspect --format='{{json .NetworkSettings.Networks}}' container3 + + {"isolated_nw": + {"IPAMConfig": + { + "IPv4Address":"172.25.3.3"}, + "NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", + "EndpointID":"dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103", + "Gateway":"172.25.0.1", + "IPAddress":"172.25.3.3", + "IPPrefixLen":16, + "IPv6Gateway":"", + "GlobalIPv6Address":"", + "GlobalIPv6PrefixLen":0, + "MacAddress":"02:42:ac:19:03:03"} + } + } } -] -``` + ``` -You can see that the Engine automatically assigns an IP address to `container2`. -Given we specified a `--subnet` when creating the network, Engine picked -an address from that same subnet. Now, start a third container and connect it to -the network on launch using the `docker run` command's `--network` option: + Because you connected `container3` to the `isolated_nw` when you started it, + it is not connected to the default `bridge` network at all. -```bash -$ docker run --network=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox +6. Inspect the network resources used by `container2`. If you have Python + installed, you can pretty print the output. -467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551 -``` + ```bash + $ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool -As you can see you were able to specify the ip address for your container. As -long as the network to which the container is connecting was created with a -user specified subnet, you will be able to select the IPv4 and/or IPv6 -address(es) for your container when executing `docker run` and `docker network -connect` commands by respectively passing the `--ip` and `--ip6` flags for IPv4 -and IPv6. The selected IP address is part of the container networking -configuration and will be preserved across container reload. The feature is -only available on user defined networks, because they guarantee their subnets -configuration does not change across daemon reload. - -Now, inspect the network resources used by `container3`. - -```bash{% raw %} -$ docker inspect --format='{{json .NetworkSettings.Networks}}' container3 - -{"isolated_nw":{"IPAMConfig":{"IPv4Address":"172.25.3.3"},"NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", -"EndpointID":"dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103","Gateway":"172.25.0.1","IPAddress":"172.25.3.3","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:19:03:03"}} -{% endraw %}``` -Repeat this command for `container2`. If you have Python installed, you can pretty print the output. - -```bash{% raw %} -$ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool - -{ - "bridge": { - "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", - "EndpointID": "0099f9efb5a3727f6a554f176b1e96fca34cae773da68b3b6a26d046c12cb365", - "Gateway": "172.17.0.1", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "IPAMConfig": null, - "IPAddress": "172.17.0.3", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "MacAddress": "02:42:ac:11:00:03" - }, - "isolated_nw": { - "NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", - "EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d", - "Gateway": "172.25.0.1", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "IPAMConfig": null, - "IPAddress": "172.25.0.2", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "MacAddress": "02:42:ac:19:00:02" + { + "bridge": { + "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", + "EndpointID": "0099f9efb5a3727f6a554f176b1e96fca34cae773da68b3b6a26d046c12cb365", + "Gateway": "172.17.0.1", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAMConfig": null, + "IPAddress": "172.17.0.3", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "MacAddress": "02:42:ac:11:00:03" + }, + "isolated_nw": { + "NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", + "EndpointID": "11cedac1810e864d6b1589d92da12af66203879ab89f4ccd8c8fdaa9b1c48b1d", + "Gateway": "172.25.0.1", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAMConfig": null, + "IPAddress": "172.25.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "MacAddress": "02:42:ac:19:00:02" + } } -} -{% endraw %}``` + ``` -You should find `container2` belongs to two networks. The `bridge` network -which it joined by default when you launched it and the `isolated_nw` which you -later connected it to. + Notice that `container2` belongs to two networks. It joined the default `bridge` + network when you launched it and you connected it to the `isolated_nw` in + step 3. -![](images/working.png) + ![](images/working.png) -In the case of `container3`, you connected it through `docker run` to the -`isolated_nw` so that container is not connected to `bridge`. - -Use the `docker attach` command to connect to the running `container2` and -examine its networking stack: - -```bash -$ docker attach container2 -``` - -If you look at the container's network stack you should see two Ethernet -interfaces, one for the default bridge network and one for the `isolated_nw` -network. - -```bash -/ # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 - inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 - inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link - UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 - RX packets:8 errors:0 dropped:0 overruns:0 frame:0 - TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) eth1 Link encap:Ethernet HWaddr 02:42:AC:15:00:02 - inet addr:172.25.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 - inet6 addr: fe80::42:acff:fe19:2/64 Scope:Link - UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 - RX packets:8 errors:0 dropped:0 overruns:0 frame:0 - TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) -lo Link encap:Local Loopback - inet addr:127.0.0.1 Mask:255.0.0.0 - inet6 addr: ::1/128 Scope:Host - UP LOOPBACK RUNNING MTU:65536 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) -``` +7. Use the `docker attach` command to connect to the running `container2` and + examine its networking stack: -On the `isolated_nw` which was user defined, the Docker embedded DNS server -enables name resolution for other containers in the network. Inside of -`container2` it is possible to ping `container3` by name. + ```bash + $ docker attach container2 + ``` -```bash -/ # ping -w 4 container3 -PING container3 (172.25.3.3): 56 data bytes -64 bytes from 172.25.3.3: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.3.3: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.3.3: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.3.3: seq=3 ttl=64 time=0.097 ms + Use the `ifconfig` command to examine the container's networking stack. you + should see two ethernet interfaces, one for the default `bridge` network, + and the other for the `isolated_nw` network. ---- container3 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms -``` + ```bash + $ sudo ifconfig -a -This isn't the case for the default `bridge` network. Both `container2` and -`container1` are connected to the default bridge network. Docker does not -support automatic service discovery on this network. For this reason, pinging -`container1` by name fails as you would expect based on the `/etc/hosts` file: + eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 + inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 + inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 + RX packets:8 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) -```bash -/ # ping -w 4 container1 -ping: bad address 'container1' -``` + eth1 Link encap:Ethernet HWaddr 02:42:AC:15:00:02 + inet addr:172.25.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 + inet6 addr: fe80::42:acff:fe19:2/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:8 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) -A ping using the `container1` IP address does succeed though: + lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:65536 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + ``` -```bash -/ # ping -w 4 172.17.0.2 -PING 172.17.0.2 (172.17.0.2): 56 data bytes -64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.095 ms -64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms -64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms -64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.101 ms +7. The Docker embedded DNS server enables name resolution for containers + connected to a given network. This means that any connected container can + ping another container on the same network by its container name. From + within `container2`, you can ping `container3` by name. ---- 172.17.0.2 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.072/0.085/0.101 ms -``` + ```bash + / # ping -w 4 container3 + PING container3 (172.25.3.3): 56 data bytes + 64 bytes from 172.25.3.3: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.3.3: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.3.3: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.3.3: seq=3 ttl=64 time=0.097 ms -If you wanted you could connect `container1` to `container2` with the `docker -run --link` command and that would enable the two containers to interact by name -as well as IP. + --- container3 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` -Detach from a `container2` and leave it running using `CTRL-p CTRL-q`. + This functionality is not available for the default `bridge` network. Both + `container1` and `container2` are connected to the `bridge` network, but + you cannot ping `container1` from `container2` using the container name. -In this example, `container2` is attached to both networks and so can talk to -`container1` and `container3`. But `container3` and `container1` are not in the -same network and cannot communicate. Test, this now by attaching to -`container3` and attempting to ping `container1` by IP address. -```bash -$ docker attach container3 + ```bash + / # ping -w 4 container1 + ping: bad address 'container1' + ``` -/ # ping 172.17.0.2 -PING 172.17.0.2 (172.17.0.2): 56 data bytes -^C ---- 172.17.0.2 ping statistics --- -10 packets transmitted, 0 packets received, 100% packet loss + You can still ping the IP address directly: -``` + ```bash + / # ping -w 4 172.17.0.2 + PING 172.17.0.2 (172.17.0.2): 56 data bytes + 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.095 ms + 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms + 64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms + 64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.101 ms -You can connect both running and non-running containers to a network. However, -`docker network inspect` only displays information on running containers. + --- 172.17.0.2 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.072/0.085/0.101 ms + ``` -### Linking containers in user-defined networks + Detach from `container2` and leave it running using `CTRL-p CTRL-q`. -In the above example, `container2` was able to resolve `container3`'s name -automatically in the user defined network `isolated_nw`, but the name -resolution did not succeed automatically in the default `bridge` network. This -is expected in order to maintain backward compatibility with [legacy -link](default_network/dockerlinks.md). +8. Currently, `container2` is attached to both `bridge` and `isolated_nw` + networks, so it can communicate with both `container1` and `container3`. + However, `container3` and `container1` do not have any networks in common, + so they cannot communicate. To verify this, attach to `container3` and try + to ping `container1` by IP address. -The `legacy link` provided 4 major functionalities to the default `bridge` -network. + ```bash + $ docker attach container3 -* name resolution -* name alias for the linked container using `--link=CONTAINER-NAME:ALIAS` + $ ping 172.17.0.2 + PING 172.17.0.2 (172.17.0.2): 56 data bytes + ^C + + --- 172.17.0.2 ping statistics --- + 10 packets transmitted, 0 packets received, 100% packet loss + + ``` + + Detach from `container3` and leave it running using `CTRL-p CTRL-q`. + +>You can connect a container to a network even if the container is not running. +However, `docker network inspect` only displays information on running containers. + +### Linking containers without using user-defined networks + +After you complete the steps in +[Basic container networking examples](#basic-container-networking-examples), +`container2` can resolve `container3`'s name automatically because both containers +are connected to the `isolated_nw` network. However, containers connected to the +default `bridge` network cannot resolve each other's container name. If you need +containers to be able to communicate with each other over the `bridge` network, +you need to use the legacy [link](default_network/dockerlinks.md) feature. +This is the only use case where using `--link` is recommended. You should +strongly consider using user-defined networks instead. + +Using the legacy `link` flag adds the following features for communication +between communication on the default `bridge` network: + +* the ability to resolve container names to IP addresses +* the ability to define a network alias as an alternate way to refer to the linked container, using `--link=CONTAINER-NAME:ALIAS` * secured container connectivity (in isolation via `--icc=false`) * environment variable injection -Comparing the above 4 functionalities with the non-default user-defined -networks such as `isolated_nw` in this example, without any additional config, -`docker network` provides +To reiterate, all of these features are provided by default when you use a +user-defined network, with no additional configuration required. **Additionally, +you get the ability to dynamically attach to and detach from multiple networks.** * automatic name resolution using DNS -* automatic secured isolated environment for the containers in a network -* ability to dynamically attach and detach to multiple networks * supports the `--link` option to provide name alias for the linked container +* automatic secured isolated environment for the containers in a network +* environment variable injection -Continuing with the above example, create another container `container4` in -`isolated_nw` with `--link` to provide additional name resolution using alias -for other containers in the same network. +The following example briefly describes how to use `--link`. -```bash -$ docker run --network=isolated_nw -itd --name=container4 --link container5:c5 busybox +1. Continuing with the above example, create a new container, `container4`, and + connect it to the network `isolated_nw`. In addition, link it to container + `container5` (which does not exist yet!) using the `--link` flag. -01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c + ```bash + $ docker run --network=isolated_nw -itd --name=container4 --link container5:c5 busybox + + 01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c + ``` + + This is a little tricky, because `container5` does not exist yet. When + `container5` is created, `container4` will be able to resolve the name `c5` to + `container5`'s IP address. + + >**Note:** Any link between containers created with *legacy link* is static in + nature and hard-binds the container with the alias. It does not tolerate + linked container restarts. The new *link* functionality in user defined + networks supports dynamic links between containers, and tolerates restarts and + IP address changes in the linked container. + + Since you have not yet created container `container5` trying to ping it will result + in an error. Attach to `container4` and try to ping either `container5` or `c5`: + + ```bash + $ docker attach container4 + + $ ping container5 + + ping: bad address 'container5' + + $ ping c5 + + ping: bad address 'c5' + + ``` + Detach from `container3` and leave it running using `CTRL-p CTRL-q`. + +2. Create another container named `container5`, and link it to `container4` + using the alias `c4`. + + + ```bash + $ docker run --network=isolated_nw -itd --name=container5 --link container4:c4 busybox + + 72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a + ``` + + Now attach to `container4` and try to ping `c5` and `container5`. + + ```bash + $ docker attach container4 + + / # ping -w 4 c5 + PING c5 (172.25.0.5): 56 data bytes + 64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms + + --- c5 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + + / # ping -w 4 container5 + PING container5 (172.25.0.5): 56 data bytes + 64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms + + --- container5 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` + Detach from `container4` and leave it running using `CTRL-p CTRL-q`. + +3. Finally, attach to `container5` and verify that you can ping `container4`. + + ```bash + $ docker attach container5 + + / # ping -w 4 c4 + PING c4 (172.25.0.4): 56 data bytes + 64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms + 64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms + 64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms + + --- c4 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.065/0.070/0.082 ms + + / # ping -w 4 container4 + PING container4 (172.25.0.4): 56 data bytes + 64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms + 64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms + 64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms + + --- container4 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.065/0.070/0.082 ms + ``` + Detach from `container5` and leave it running using `CTRL-p CTRL-q`. + +### Network alias scoping example + +When you link containers, whether using the legacy `link` method or using +user-defined networks, any aliases you specify only have meaning to the +container where they are specified, and won't work on other containers on the +default `bridge` network. + +In addition, if a container belongs to multiple networks, a given linked alias +is scoped within a given network. Thus, a container can be linked to different +aliases in different networks, and the aliases will not work for containers which +are not on the same network. + +The following example illustrates these points. + +1. Create another network named `local_alias` + + ```bash + $ docker network create -d bridge --subnet 172.26.0.0/24 local_alias + 76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa ``` -With the help of `--link` `container4` will be able to reach `container5` using -the aliased name `c5` as well. - -Please note that while creating `container4`, we linked to a container named -`container5` which is not created yet. That is one of the differences in -behavior between the *legacy link* in default `bridge` network and the new -*link* functionality in user defined networks. The *legacy link* is static in -nature and it hard-binds the container with the alias and it doesn't tolerate -linked container restarts. While the new *link* functionality in user defined -networks are dynamic in nature and supports linked container restarts including -tolerating ip-address changes on the linked container. - -Now let us launch another container named `container5` linking `container4` to -c4. - -```bash -$ docker run --network=isolated_nw -itd --name=container5 --link container4:c4 busybox - -72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a -``` - -As expected, `container4` will be able to reach `container5` by both its -container name and its alias c5 and `container5` will be able to reach -`container4` by its container name and its alias c4. - -```bash -$ docker attach container4 - -/ # ping -w 4 c5 -PING c5 (172.25.0.5): 56 data bytes -64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms - ---- c5 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms - -/ # ping -w 4 container5 -PING container5 (172.25.0.5): 56 data bytes -64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms - ---- container5 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms -``` - -```bash -$ docker attach container5 - -/ # ping -w 4 c4 -PING c4 (172.25.0.4): 56 data bytes -64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms -64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms -64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms -64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms - ---- c4 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.065/0.070/0.082 ms - -/ # ping -w 4 container4 -PING container4 (172.25.0.4): 56 data bytes -64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms -64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms -64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms -64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms - ---- container4 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.065/0.070/0.082 ms -``` - -Similar to the legacy link functionality the new link alias is localized to a -container and the aliased name has no meaning outside of the container using -the `--link`. - -Also, it is important to note that if a container belongs to multiple networks, -the linked alias is scoped within a given network. Hence the containers can be -linked to different aliases in different networks. - -Extending the example, let us create another network named `local_alias` - -```bash -$ docker network create -d bridge --subnet 172.26.0.0/24 local_alias -76b7dc932e037589e6553f59f76008e5b76fa069638cd39776b890607f567aaa -``` - -let us connect `container4` and `container5` to the new network `local_alias` - -``` -$ docker network connect --link container5:foo local_alias container4 -$ docker network connect --link container4:bar local_alias container5 -``` - -```bash -$ docker attach container4 - -/ # ping -w 4 foo -PING foo (172.26.0.3): 56 data bytes -64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms - ---- foo ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms - -/ # ping -w 4 c5 -PING c5 (172.25.0.5): 56 data bytes -64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms - ---- c5 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms -``` - -Note that the ping succeeds for both the aliases but on different networks. Let -us conclude this section by disconnecting `container5` from the `isolated_nw` -and observe the results - -``` -$ docker network disconnect isolated_nw container5 - -$ docker attach container4 - -/ # ping -w 4 c5 -ping: bad address 'c5' - -/ # ping -w 4 foo -PING foo (172.26.0.3): 56 data bytes -64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms - ---- foo ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms - -``` - -In conclusion, the new link functionality in user defined networks provides all -the benefits of legacy links while avoiding most of the well-known issues with -*legacy links*. - -One notable missing functionality compared to *legacy links* is the injection -of environment variables. Though very useful, environment variable injection is -static in nature and must be injected when the container is started. One cannot -inject environment variables into a running container without significant -effort and hence it is not compatible with `docker network` which provides a -dynamic way to connect/ disconnect containers to/from a network. +2. Next, connect `container4` and `container5` to the new network `local_alias` + with the aliases `foo` and `bar`: -### Network-scoped alias + ```bash + $ docker network connect --link container5:foo local_alias container4 + $ docker network connect --link container4:bar local_alias container5 + ``` -While *link*s provide private name resolution that is localized within a -container, the network-scoped alias provides a way for a container to be -discovered by an alternate name by any other container within the scope of a -particular network. Unlike the *link* alias, which is defined by the consumer -of a service, the network-scoped alias is defined by the container that is -offering the service to the network. +3. Attach to `container3` and try to ping `container4` using alias `foo`, then + try pinging container `container5` using alias `c5`: -Continuing with the above example, create another container in `isolated_nw` -with a network alias. - -```bash -$ docker run --network=isolated_nw -itd --name=container6 --network-alias app busybox + ```bash + $ docker attach container4 -8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17 -``` + / # ping -w 4 foo + PING foo (172.26.0.3): 56 data bytes + 64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms -```bash -$ docker attach container4 + --- foo ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms -/ # ping -w 4 app -PING app (172.25.0.6): 56 data bytes -64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + / # ping -w 4 c5 + PING c5 (172.25.0.5): 56 data bytes + 64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms ---- app ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms + --- c5 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` -/ # ping -w 4 container6 -PING container5 (172.25.0.6): 56 data bytes -64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + Both pings succeed, but the subnets are different, which means that the + networks are different. ---- container6 ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms -``` + Detach from `container4` and leave it running using `CTRL-p CTRL-q`. -Now let us connect `container6` to the `local_alias` network with a different -network-scoped alias. +4. Disconnect `container5` from the `isolated_nw` network. Attach to `container4` + and try pinging `c5` and `foo`. -```bash -$ docker network connect --alias scoped-app local_alias container6 -``` + ``` + $ docker network disconnect isolated_nw container5 -`container6` in this example now is aliased as `app` in network `isolated_nw` -and as `scoped-app` in network `local_alias`. + $ docker attach container4 -Let's try to reach these aliases from `container4` (which is connected to both -these networks) and `container5` (which is connected only to `isolated_nw`). + / # ping -w 4 c5 + ping: bad address 'c5' -```bash -$ docker attach container4 + / # ping -w 4 foo + PING foo (172.26.0.3): 56 data bytes + 64 bytes from 172.26.0.3: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.26.0.3: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.3: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.3: seq=3 ttl=64 time=0.097 ms -/ # ping -w 4 scoped-app -PING foo (172.26.0.5): 56 data bytes -64 bytes from 172.26.0.5: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.26.0.5: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.26.0.5: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.26.0.5: seq=3 ttl=64 time=0.097 ms + --- foo ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms ---- foo ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` -$ docker attach container5 + You can no longer reach containers on the `isolated_nw` network from `container5`. + However, you can still reach `container4` (from `container4`) using the alias + `foo`. -/ # ping -w 4 scoped-app -ping: bad address 'scoped-app' + Detach from `container4` and leave it running using `CTRL-p CTRL-q`. -``` +### Limitations of `docker network` -As you can see, the alias is scoped to the network it is defined on and hence -only those containers that are connected to that network can access the alias. +Although `docker network` is the recommended way to control the networks your +containers use, it does have some limitations. -In addition to the above features, multiple containers can share the same -network-scoped alias within the same network. For example, let's launch -`container7` in `isolated_nw` with the same alias as `container6` +#### Environment variable injection -```bash -$ docker run --network=isolated_nw -itd --name=container7 --network-alias app busybox +Environment variable injection is static in nature and environment variables +cannot be changed after a container is started. The legacy `--link` flag shares +all environment variables to the linked container, but the `docker network` command +has no equivalent. When you connect to a network using `docker network`, no +environment variables can be dynamically among containers. -3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554 -``` +#### Understanding network-scoped aliases -When multiple containers share the same alias, name resolution to that alias -will happen to one of the containers (typically the first container that is -aliased). When the container that backs the alias goes down or disconnected -from the network, the next container that backs the alias will be resolved. +Legacy links provide outgoing name resolution that is isolated within the +container in which the alias is configured. Network-scoped aliases do not allow +for this one-way isolation, but provide the alias to all members of the network. -Let us ping the alias `app` from `container4` and bring down `container6` to -verify that `container7` is resolving the `app` alias. +The following example illustrates this limitation. -```bash -$ docker attach container4 +1. Create another container called `container6` in the network `isolated_nw` + and give it the network alias `app`. -/ # ping -w 4 app -PING app (172.25.0.6): 56 data bytes -64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms -64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms -64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + ```bash + $ docker run --network=isolated_nw -itd --name=container6 --network-alias app busybox ---- app ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.070/0.081/0.097 ms + 8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17 + ``` -$ docker stop container6 +2. Attach to `container4`. Try pinging the container by name (`container6`) and by + network alias (`app`). Notice that the IP address is the same. -$ docker attach container4 + ```bash + $ docker attach container4 -/ # ping -w 4 app -PING app (172.25.0.7): 56 data bytes -64 bytes from 172.25.0.7: seq=0 ttl=64 time=0.095 ms -64 bytes from 172.25.0.7: seq=1 ttl=64 time=0.075 ms -64 bytes from 172.25.0.7: seq=2 ttl=64 time=0.072 ms -64 bytes from 172.25.0.7: seq=3 ttl=64 time=0.101 ms + / # ping -w 4 app + PING app (172.25.0.6): 56 data bytes + 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms ---- app ping statistics --- -4 packets transmitted, 4 packets received, 0% packet loss -round-trip min/avg/max = 0.072/0.085/0.101 ms + --- app ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms -``` + / # ping -w 4 container6 + PING container5 (172.25.0.6): 56 data bytes + 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + + --- container6 ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` + + Detach from `container4` and leave it running using `CTRL-p CTRL-q`. + + +3. Connect `container6` to the `local_alias` network with the network-scoped + alias `scoped-app`. + + ```bash + $ docker network connect --alias scoped-app local_alias container6 + ``` + + Now `container6` is aliased as `app` in network `isolated_nw` + and as `scoped-app` in network `local_alias`. + + +4. Try to reach these aliases from `container4` (which is connected to both + these networks) and `container5` (which is connected only to `isolated_nw`). + + ```bash + $ docker attach container4 + + / # ping -w 4 scoped-app + PING foo (172.26.0.5): 56 data bytes + 64 bytes from 172.26.0.5: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.26.0.5: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.5: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.26.0.5: seq=3 ttl=64 time=0.097 ms + + --- foo ping statistics --- + 4 packets transmitted, 4 packets received, 0% packet loss + round-trip min/avg/max = 0.070/0.081/0.097 ms + ``` + Detach from `container4` and leave it running using `CTRL-p CTRL-q`. + + ```bash + $ docker attach container5 + + / # ping -w 4 scoped-app + ping: bad address 'scoped-app' + + ``` + + Detach from `container5` and leave it running using `CTRL-p CTRL-q`. + +This shows that an alias is scoped to the network where it is defined, and only +containers connected to that network can access the alias. + + +#### Resolving multiple containers to a single alias + +Multiple containers can share the same network-scoped alias within the same +network. This example illustrates how this works. + +1. Launch `container7` in `isolated_nw` with the same alias as `container6`, + which is `app`. + + ```bash + $ docker run --network=isolated_nw -itd --name=container7 --network-alias app busybox + + 3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554 + ``` + + When multiple containers share the same alias, one of those containers + will resolve to the alias. If that container is unavailable, another + container with the alias will be resolved. This provides a sort of high + availability within the cluster. + + > When the IP address is resolved, the container chosen to resolve it is + random. For that reason, in the exercises below, you may get different + results in some steps. If the step assumes the result returned is `container6` + but you get `container7`, this is why. + +2. Start a continuous ping from `container4` to the `app` alias. + + ```bash + $ docker attach container4 + + $ ping app + PING app (172.25.0.6): 56 data bytes + 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + ... + ``` + + The IP address that is returned belongs to `container6`. + +3. In another terminal, stop `container6`. + ```bash + $ docker stop container6 + ``` + + In the terminal attached to `container4`, observe the `ping` output. + It will pause when `container6` goes down, because the `ping` command + looks up the IP when it is first invoked, and that IP is no longer reachable. + However, the `ping` command has a very long timeout by default, so no error + occurs. + +4. Exit the `ping` command using `CTRL+C` and run it again. + + ```bash + $ ping app + + PING app (172.25.0.7): 56 data bytes + 64 bytes from 172.25.0.7: seq=0 ttl=64 time=0.095 ms + 64 bytes from 172.25.0.7: seq=1 ttl=64 time=0.075 ms + 64 bytes from 172.25.0.7: seq=2 ttl=64 time=0.072 ms + 64 bytes from 172.25.0.7: seq=3 ttl=64 time=0.101 ms + ... + ``` + + The `app` alias now resolves to the IP address of `container7`. + +5. For one last test, restart `container6`. + + ```bash + $ docker start container6 + ``` + + In the terminal attached to `container4`, run the `ping` command again. It + might now resolve to `container6` again. If you start and stop the `ping` + several times, you will see responses from each of the containers. + + ```bash + $ docker attach container4 + + $ ping app + PING app (172.25.0.6): 56 data bytes + 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms + 64 bytes from 172.25.0.6: seq=1 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=2 ttl=64 time=0.080 ms + 64 bytes from 172.25.0.6: seq=3 ttl=64 time=0.097 ms + ... + ``` + + Stop the ping with `CTRL+C`. Detach from `container4` and leave it running + using `CTRL-p CTRL-q`. ## Disconnecting containers -You can disconnect a container from a network using the `docker network +You can disconnect a container from a network at any time using the `docker network disconnect` command. -```bash{% raw %} -$ docker network disconnect isolated_nw container2 +1. Disconnect `container2` from the `isolated_nw` network, then inspect `container2` + and the `isolated_nw` network. -$ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool + ```bash + $ docker network disconnect isolated_nw container2 -{ - "bridge": { - "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", - "EndpointID": "9e4575f7f61c0f9d69317b7a4b92eefc133347836dd83ef65deffa16b9985dc0", - "Gateway": "172.17.0.1", - "GlobalIPv6Address": "", - "GlobalIPv6PrefixLen": 0, - "IPAddress": "172.17.0.3", - "IPPrefixLen": 16, - "IPv6Gateway": "", - "MacAddress": "02:42:ac:11:00:03" - } -} + $ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool - -$ docker network inspect isolated_nw - -[ { - "Name": "isolated_nw", - "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", - "Scope": "local", - "Driver": "bridge", - "IPAM": { - "Driver": "default", - "Config": [ - { - "Subnet": "172.21.0.0/16", - "Gateway": "172.21.0.1/16" - } - ] - }, - "Containers": { - "467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551": { - "Name": "container3", - "EndpointID": "dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103", - "MacAddress": "02:42:ac:19:03:03", - "IPv4Address": "172.25.3.3/16", - "IPv6Address": "" - } - }, - "Options": {} + "bridge": { + "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", + "EndpointID": "9e4575f7f61c0f9d69317b7a4b92eefc133347836dd83ef65deffa16b9985dc0", + "Gateway": "172.17.0.1", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAddress": "172.17.0.3", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "MacAddress": "02:42:ac:11:00:03" + } } -] -{% endraw %}``` -Once a container is disconnected from a network, it cannot communicate with -other containers connected to that network. In this example, `container2` can -no longer talk to `container3` on the `isolated_nw` network. -```bash -$ docker attach container2 + $ docker network inspect isolated_nw -/ # ifconfig -eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 - inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 - inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link - UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 - RX packets:8 errors:0 dropped:0 overruns:0 frame:0 - TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) + [ + { + "Name": "isolated_nw", + "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", + "Scope": "local", + "Driver": "bridge", + "IPAM": { + "Driver": "default", + "Config": [ + { + "Subnet": "172.21.0.0/16", + "Gateway": "172.21.0.1/16" + } + ] + }, + "Containers": { + "467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551": { + "Name": "container3", + "EndpointID": "dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103", + "MacAddress": "02:42:ac:19:03:03", + "IPv4Address": "172.25.3.3/16", + "IPv6Address": "" + } + }, + "Options": {} + } + ] + ``` -lo Link encap:Local Loopback - inet addr:127.0.0.1 Mask:255.0.0.0 - inet6 addr: ::1/128 Scope:Host - UP LOOPBACK RUNNING MTU:65536 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) -/ # ping container3 -PING container3 (172.25.3.3): 56 data bytes -^C ---- container3 ping statistics --- -2 packets transmitted, 0 packets received, 100% packet loss +2. When a container is disconnected from a network, it can no longer communicate + with other containers connected to that network, unless it has other networks + in common with them. Verify that `container2` can no longer reach `container3`, + which is on the `isolated_nw` network. + + ```bash + $ docker attach container2 + + / # ifconfig + eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 + inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 + inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1 + RX packets:8 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) + + lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:65536 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + + / # ping container3 + PING container3 (172.25.3.3): 56 data bytes + ^C + --- container3 ping statistics --- + 2 packets transmitted, 0 packets received, 100% packet loss + ``` + +3. Verify that `container2` still has full connectivity to the default `bridge` + network. + + ```bash + / # ping container1 + PING container1 (172.17.0.2): 56 data bytes + 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.119 ms + 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.174 ms + ^C + --- container1 ping statistics --- + 2 packets transmitted, 2 packets received, 0% packet loss + round-trip min/avg/max = 0.119/0.146/0.174 ms + / # + ``` + +4. Remove `container4`, `container5`, `container6`, and `container7`. + ```bash + $ docker stop container4 container5 container6 container7 + + $ docker rm container4 container5 container6 container7 + ``` + +### Handling stale network endpoints + +In some scenarios, such as ungraceful docker daemon restarts in a +multi-host network, the daemon cannot clean up stale connectivity endpoints. +Such stale endpoints may cause an error if a new container is connected +to that network with the same name as the stale endpoint: + +```no-highlight +ERROR: Cannot start container bc0b19c089978f7845633027aa3435624ca3d12dd4f4f764b61eac4c0610f32e: container already connected to network multihost ``` -The `container2` still has full connectivity to the bridge network - -```bash -/ # ping container1 -PING container1 (172.17.0.2): 56 data bytes -64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.119 ms -64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.174 ms -^C ---- container1 ping statistics --- -2 packets transmitted, 2 packets received, 0% packet loss -round-trip min/avg/max = 0.119/0.146/0.174 ms -/ # -``` - -There are certain scenarios such as ungraceful docker daemon restarts in -multi-host network, where the daemon is unable to cleanup stale connectivity -endpoints. Such stale endpoints may cause an error `container already connected -to network` when a new container is connected to that network with the same -name as the stale endpoint. In order to cleanup these stale endpoints, first -remove the container and force disconnect (`docker network disconnect -f`) the -endpoint from the network. Once the endpoint is cleaned up, the container can -be connected to the network. +To clean up these stale endpoints, remove the container and disconnect it +from the network forcibly (`docker network disconnect -f`). Now you can +successfully connect the container to the network. ```bash $ docker run -d --name redis_db --network multihost redis @@ -870,47 +1019,56 @@ $ docker run -d --name redis_db --network multihost redis ## Remove a network When all the containers in a network are stopped or disconnected, you can -remove a network. +remove a network. If a network has connected endpoints, an error occurs. -```bash -$ docker network disconnect isolated_nw container3 -``` +1. Disconnect `container3` from `isolated_nw`. -```bash -$ docker network inspect isolated_nw + ```bash + $ docker network disconnect isolated_nw container3 + ``` -[ - { - "Name": "isolated_nw", - "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", - "Scope": "local", - "Driver": "bridge", - "IPAM": { - "Driver": "default", - "Config": [ - { - "Subnet": "172.21.0.0/16", - "Gateway": "172.21.0.1/16" - } - ] - }, - "Containers": {}, - "Options": {} - } -] +2. Inspect `isolated_nw` to verify that no other endpoints are connected to it. -$ docker network rm isolated_nw -``` + ```bash + $ docker network inspect isolated_nw -List all your networks to verify the `isolated_nw` was removed: + [ + { + "Name": "isolated_nw", + "Id": "06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8", + "Scope": "local", + "Driver": "bridge", + "IPAM": { + "Driver": "default", + "Config": [ + { + "Subnet": "172.21.0.0/16", + "Gateway": "172.21.0.1/16" + } + ] + }, + "Containers": {}, + "Options": {} + } + ] + ``` +3. Remove the `isolated_nw` network. + ```bash + $ docker network rm isolated_nw + ``` + +4. List all your networks to verify that `isolated_nw` no longer exists: ```bash $ docker network ls -NETWORK ID NAME DRIVER -72314fa53006 host host -f7ab26d71dbd bridge bridge -0f32e83e61ac none null +NETWORK ID NAME DRIVER SCOPE +4bb8c9bf4292 bridge bridge local +43575911a2bd host host local +76b7dc932e03 local_alias bridge local +b1a086897963 my-network bridge local +3eb020e70bfd none null local +69568e6336d8 simple-network bridge local ``` ## Related information @@ -920,4 +1078,4 @@ f7ab26d71dbd bridge bridge * [network connect](../../reference/commandline/network_connect.md) * [network disconnect](../../reference/commandline/network_disconnect.md) * [network ls](../../reference/commandline/network_ls.md) -* [network rm](../../reference/commandline/network_rm.md) \ No newline at end of file +* [network rm](../../reference/commandline/network_rm.md)