Bind the Dokcer container to the host to specify the network card method

  • 2020-10-23 21:18:01
  • OfStack

If your host has multiple network CARDS, you may need to bind the Docker container to the specified network card so that all network requests within the container are sent to the external network through the specified network card.

Unfortunately, Docker does not directly provide a way to implement this requirement. With iptables, however, you can easily do this.

1 knife

Suppose you have two network CARDS on your host computer: the IP address of one network card is 192.168.0.100; The IP address of the other network card is 10.0.0.100. You want all the services in the Docker container on this host to go through the second network card in and out of the network.

Give the answer first and then explain:

iptables -t nat -I POSTROUTING -p all -s 172.17.0.0/16 -j SNAT --to-source 10.0.0.100

The iptables command above creates a source address translation (SNAT) rule that changes the source IP address to 10.0.0.100 for all packets coming out of the host from the 172.17.0.0/16 network segment.

For 10.0.0.100 we know that it is the IP address of the host's second network card. And where did 172.17.0.0/16 come from?

Simply put, when running Docker on the host, it creates a network bridge named docker0 on the host with its IP address of 172.17.0.1 and network segment of 172.17.0.0/16. By default, Docker allocates one IP address for all containers from the segment.

For more details, please refer to the article "Default Network Configuration of Docker under Single Host".

The IP address of all Docker containers is in the 172.17.0.0/16 segment. Then, the above iptables command creates a rule that changes the source IP address of all packets coming out of the Docker container to the IP address of the second network card of the host, i.e. 10.0.0.100.

In this way, we have achieved the "out" half of our requirements.

The implementation of the "forward" part of the requirements is also very simple, as long as the host IP is specified by the -p parameter when docker run is used, such as:


docker run -p 10.0.0.100:80:80 ...

Divide and rule

Demand is changing fast, maybe we have an additional network card with IP address 10.0.0.101. For some reason, we want the traffic of part 1 container to go through the second network card, and the traffic of part 1 container to go through the newly added third network card.

Since Docker does not allow IP addresses to be specified for containers when using the default bridge (Docker gives the following error message if you specify IP), we cannot predict in advance what IP address a container will eventually be assigned to and therefore cannot specify an exit card for it through the iptables rule.

[

docker: Error response from daemon: user specified IP address is supported on user defined networks only.

]

In fact, the error message above has already given the solution, that is, user-defined network.

Create a custom network with the following command:

docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1"  docker1

Among them, 172.18.0.0/16 is the network segment where the new bridge is located. Because the default Dokcer bridge is already occupied by 172.17.0.0/16, the new bridge can only use unused segments of the network.

First docker1 for execution ifconfig - a command, display of the bridge, if you don't use - opt parameter to specify the name, that you're using ifconfig - a command to check the network information, see is like eb56a0b22 br - 110 name. This is obviously not pretty/memorable;

The second docker1 is the bridge name displayed when the docker network list command is executed.

With a custom network, we can specify a fixed IP address for the container.


docker run --network=docker1 --ip=172.18.0.100 ......
docker run --network=docker1 --ip=172.18.0.101 ......

Knowing the container's fixed IP address, we can do the same and bind the container to the specified host network card:


iptables -t nat -I POSTROUTING -p all -s 172.18.0.100 -j SNAT --to-source 10.0.0.100
iptables -t nat -I POSTROUTING -p all -s 172.18.0.101 -j SNAT --to-source 10.0.0.101

Note that the -ES114en option is followed by the IP address, not the segment.

Other relevant commands

View the iptables rule


iptables -t nat -L -n --line-number

Delete the iptables rule


iptables -t nat -D POSTROUTING 11

Where the last 11 is the rule number to delete (num).

Delete Docker custom network


docker network rm docker1

Related articles: