Troubleshoot: Port Range Forwarding with -p Option is Unstable on Docker.

07/03/2020Docker,InfrastructureDocker,Network,Troubleshooting

Port Forwarding Feature on Docker

As you know, on Docker, you can set port forwarding between host server and containers with the following command.

$ docker container run -p [host port]:[container port] [image name]

Example: Create Nginx container. In this case the packets coming to 80 port on the host server will be forwarded to 8080 port on Nginx container.

$ docker container run -p 80:8080 nginx


Port Range Forwarding is Unstable on Docker

Actually, you can set port forwarding with range.

$ docker container run -p [host start port]-[host end port]:[container start port]-[container end port] [image name]

However, if you set long range like “-p 13000-15999:13000-15999", System consume a lot of RAM , and docker’s network may become unstable.


Reason Why Docker Becomes Unstable?

Docker’s networking system uses “iptables" function internally. Based on the values subsequent the -p option in the docker command , Docker add some forwarding rules to the iptables.

For example, if you set ranged ports like “-p 31000-31200" , ridiculously Docker will add forwarding rules of each port to the iptables one by one instead of range.

You can check with “iptables -nL" command.

$  iptables -nL

target     prot opt source               destination
:
:
Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31200
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31200
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31199
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31199
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31198
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31198
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31197
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31197
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31196
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31196
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31195
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31195
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31194
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31194
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31193
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31193
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31192
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31192
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31191
ACCEPT     udp  --  0.0.0.0/0            172.20.0.11          udp dpt:31191
ACCEPT     tcp  --  0.0.0.0/0            172.20.0.11          tcp dpt:31190
:
:


Solutions for the problem

Option 1. Don’t use port forwarding with -p option when system use many ports.

In this option, the container is use host network instead of local network.


Opton 2. Add port forwarding rules to iptables without docker commands.

At the host server, with iptables commands, you can manually add port forwarding rules as range.

Example: Add port forwarding rule with range.

Host : 172.20.0.1

Container : 172.20.0.11

Port Forwarding Range : 31000-31200 / TCP

$ iptables -A INPUT -p tcp -m multiport --dports 31000:31200 -j ACCEPT
$ iptables -t nat -I PREROUTING -p tcp -m tcp --dport 31000:31200 -j DNAT --to-destination 172.20.0.11:31000-31200
$ iptables -A FORWARD -d 172.20.0.1/32 -i eth0 -p tcp -m tcp --dport 31000:31200 -j ACCEPT