Files
docker-docs/engine/userguide/networking/default_network/container-communication.md
Misty Stanley-Jones a4f5e30249 Various copyedits to reduce future tense, wordiness, and use of 'please' (#5788)
* Reword lots of instances of 'will'

* Reword lots of instances of won't

* Reword lots of instances of we'll

* Eradicate you'll

* Eradicate 'be able to' type of phrases

* Eradicate 'unable to' type of phrases

* Eradicate 'has / have to' type of phrases

* Eradicate 'note that' type of phrases

* Eradicate 'in order to' type of phrases

* Redirect to official Chef and Puppet docs

* Eradicate gratuitous 'please'

* Reduce use of e.g.

* Reduce use of i.e.

* Reduce use of N.B.

* Get rid of 'sexagesimal' and correct some errors
2018-01-25 17:37:23 -08:00

7.2 KiB

description, keywords, title
description keywords title
Understand container communication docker, container, communication, network Understand container communication

The information in this section explains container communication within the Docker default bridge. This is a bridge network named bridge created automatically when you install Docker.

Note: The Docker networks feature allows you to create user-defined networks in addition to the default bridge network.

Communicating to the outside world

Whether a container can talk to the world is governed by two factors. The first factor is whether the host machine is forwarding its IP packets. The second is whether the host's iptables allow this particular connection.

IP packet forwarding is governed by the ip_forward system parameter. Packets can only pass between containers if this parameter is 1. Usually, the default setting of --ip-forward=true is correct, and causes and Docker to set ip_forward to 1 for you when the server starts up. If you set --ip-forward=false and your system's kernel has it enabled, the --ip-forward=false option has no effect. To check the setting on your kernel or to turn it on manually:

  $ sysctl net.ipv4.conf.all.forwarding

  net.ipv4.conf.all.forwarding = 0

  $ sysctl net.ipv4.conf.all.forwarding=1

  $ sysctl net.ipv4.conf.all.forwarding

  net.ipv4.conf.all.forwarding = 1

Note

: this setting does not affect containers that use the host network stack (--network=host).

Many using Docker need ip_forward to be on, to at least make communication possible between containers and the wider world. May also be needed for inter-container communication if you are in a multiple bridge setup.

Docker never makes changes to your system iptables rules if you set --iptables=false when the daemon starts. Otherwise the Docker server appends forwarding rules to the DOCKER filter chain.

Docker flushes any pre-existing rules from the DOCKER and DOCKER-ISOLATION filter chains, if they exist. For this reason, any rules needed to further restrict access to containers need to be added after Docker has started.

Docker's forward rules permit all external source IPs by default. To allow only a specific IP or network to access the containers, insert a negated rule at the top of the DOCKER filter chain. For example, to restrict external access such that only source IP 8.8.8.8 can access the containers, the following rule could be added:

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

where ext_if is the name of the interface providing external connectivity to the host.

Communication between containers

Whether two containers can communicate is governed, at the operating system level, by two factors.

  • Does the network topology even connect the containers' network interfaces? By default Docker attaches all containers to a single docker0 bridge, providing a path for packets to travel between them. See the later sections of this document for other possible topologies.

  • Do your iptables allow this particular connection? Docker never makes changes to your system iptables rules if you set --iptables=false when the daemon starts. Otherwise the Docker server adds a default rule to the FORWARD chain with a blanket ACCEPT policy if you retain the default --icc=true, or else sets the policy to DROP if --icc=false.

It is a strategic question whether to leave --icc=true or change it to --icc=false so that iptables can protect other containers, and the Docker host, from having arbitrary ports probed or accessed by a container that gets compromised.

If you choose the most secure setting of --icc=false, then how can containers communicate in those cases where you want them to provide each other services? The answer is the --link=CONTAINER_NAME_or_ID:ALIAS option, which was mentioned in the previous section because of its effect upon name services. If the Docker daemon is running with both --icc=false and --iptables=true then, when it sees docker run invoked with the --link= option, the Docker server inserts a pair of iptables ACCEPT rules so that the new container can connect to the ports exposed by the other container -- the ports that it mentioned in the EXPOSE lines of its Dockerfile.

Note

: The value CONTAINER_NAME in --link= must either be an auto-assigned Docker name like stupefied_pare or the name you assigned with --name= when you ran docker run. It cannot be a hostname, which Docker does not recognize in the context of the --link= option.

You can run the iptables command on your Docker host to see whether the FORWARD chain has a default policy of ACCEPT or DROP:

# When --icc=false, you should see a DROP rule:

$ sudo iptables -L -n

...
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0
DROP       all  --  0.0.0.0/0            0.0.0.0/0
...

# When a --link= has been created under --icc=false,
# you should see port-specific ACCEPT rules overriding
# the subsequent DROP policy for all other packets:

$ sudo iptables -L -n

...
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0
DROP       all  --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  172.17.0.2           172.17.0.3           tcp spt:80
ACCEPT     tcp  --  172.17.0.3           172.17.0.2           tcp dpt:80

Note

: Docker is careful that its host-wide iptables rules fully expose containers to each other's raw IP addresses, so connections from one container to another should always appear to be originating from the first container's own IP address.

Container communication between hosts

For security reasons, Docker configures the iptables rules to prevent containers from forwarding traffic from outside the host machine, on Linux hosts. Docker sets the default policy of the FORWARD chain to DROP.

To override this default behavior you can manually change the default policy:

$ sudo iptables -P FORWARD ACCEPT

The iptables settings are lost when the system reboots. If you want the change to be permanent, refer to your Linux distribution's documentation.

Note

: In Docker 1.12 and earlier, the default FORWARD chain policy was ACCEPT. When you upgrade to Docker 1.13 or higher, this default is automatically changed for you.

If you had a previously working configuration with multiple containers spanned over multiple hosts, this change may cause the existing setup to stop working if you do not intervene.

Why would you need to change the default DROP to ACCEPT?

Suppose you have two hosts and each has the following configuration

host1: eth0/192.168.7.1, docker0/172.17.0.0/16
host2: eth0/192.168.8.1, docker0/172.18.0.0/16

If the container running on host1 needs the ability to communicate directly with a container on host2, you need a route from host1 to host2. After the route exists, host2 needs the ability to accept packets destined for its running container, and forward them along. Setting the policy to ACCEPT accomplishes this.