docker dynamic map run container port
2016-01-26
Docker the expose command, you can map container internal ports by writing Dockerfile plus-p parameters, but for already running container, if you want to open up a new port, It's not easy to edit dockerfile and build again.
In fact, Docker itself uses iptables to do port mapping, so we can use some simple operation to implement dynamic mapping of the container port.
You can see the specific port mappings by running the iptables command (the following example has IP-192.168.42.41 container open 22 and 20280 ports)
[Yaxin@ubox ~] $sudo iptables-nvxl Chain INPUT (policy ACCEPT 262 packets, 529689 bytes) pkts bytes Target PR OT opt in Out source destination 14355 789552 DROP TCP--* * 0.0.0.0/0 0.0.0.0/0 TCP dpt:25 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes Target PR OT opt in Out source destination 5479459 653248187 Docker All--Docker0 0.0.0.0/0 0.0.0.0/0 93990 314970368 ACCEPT all Docker0 0.0.0.0/0 E related,established 4705395 2183219154 ACCEPT All-Docker0!docker0 0.0.0.0/0-0.0.0.0/0 0 0 ACCEPT All--Docker0 Docker0 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (Policy ACCEPT 282 packets, 62249 5 bytes) pkts bytes Target prot opt in out source destination Chain Docker (1 referenc es) pkts bytesTarget prot opt in Out source destination 218 13193 ACCEPT TCP--! Docker0 Docker0 0.0.0.0/0 192.168.42.41 TCP dpt:22280 4868186 297463902 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0 /0 192.168.42.41 TCP dpt:20280 78663 13128102 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0/0 192.168.42.41 TCP dpt:22 4321 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0/0 192.168.4 2.41 TCP dpt:28159 [Yaxin@ubox ~] $sudo iptables-t NAT-NVXL Chain prerouting (Policy ACCEPT 210199 packets, 140358 bytes) pkts bytes Target prot opt in Out source destination 1219483 82563968 Docker All--* * 0.0.0.0/0 0.0.0.0/0 addrtype match Dst-type local Chain INPUT (policy ACCEPT 197679 packets, 13316595 bytes) pkts bytes Target prot opt in Out source Destina tion Chain OUTPUT (PoliCy ACCEPT 271553 packets, 16671466 bytes) pkts bytes Target prot opt in Out source dest Ination 1643 99251 Docker all 0.0.0.0/0!127.0.0.0/8 match AddrType Type local Chain postrouting (policy ACCEPT 271743 packets, 16682594 bytes) pkts bytes Target prot opt in Out source destination 13468 811013 Masquerade All--*!docker0 192.168.42.0/24 0.
0.0.0/0 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:22280 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:20280 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:22 0 0 Masquerade T CP--* * 192.168.42.41 192.168.42.41 TCP dpt:28159 Chain Docker (2 references) pkts Bytes Target Prot opT in Out source destination 1404 Dnat TCP--! Docker0 * 0.0.0.0/0 0.0.0.0/0 TCP dpt:22280 to:192.168.42.41:22280 17156 dnat TCP--! Docker0 * 0.0.0 0.0.0.0/0 TCP dpt:20280 to:192.168.42.41:20280 0/0 5952 dnat TCP--! DOCKER0 * 0.0.0.0/0 0.0.0.0/0 TCP dpt:22222 to:192.168.42.41:22 8 dnat TCP--!
DOCKER0 * 0.0.0.0/0 0.0.0.0/0 TCP dpt:28159 to:192.168.42.41:28159
All we have to do is configure the Iptables rules according to our own container.
First is the filter This table, we want to configure its release forwarding, Docker default has been all the forward rules into the Docker chain (chain), so convenient configuration, but also easy to view.
Then configure the NAT table to configure Dnat, which is the core configuration of port forwarding. This table only needs to configure postrouting and Docker chain can, here is not why this configuration, if you want to know more about iptables please google.
Here's an example:
If I have a container, the name is Nginx (by running Docker PS command can be queried), now I run the Nginx program inside the Docker, listening to 8888 ports, I hope that the extranet through the 8899-port (note the port) access Find IP assigned by Docker for Nginx
[Yaxin@ubox ~] $sudo Docker inspect-f ' {{. Networksettings.ipaddress}} ' Nginx
192.168.42.43
Configure the Forward (Docker) chain for the filter table in Iptables
[Yaxin@ubox ~] $sudo iptables-a Docker! -I docker0-o docker0-p tcp--dport 8888-d 192.168.42.43-j ACCEPT
Configure Prerouting (Docker) and postrouting chains for NAT tables in Iptables
[Yaxin@ubox ~] $sudo iptables-t nat-a postrouting-p tcp--dport 8888-s 192.168.42.43-d 192.168.42.43-j MASQUERADE
[yaxin@ubox ~] $sudo iptables-t nat-a Docker! -I dokcer0-p TCP--dport 8899-j dnat--to-destination 192.168.42.43:8888
Access to Curl http://IP:8899 through extranet shows HTML pages configured under Nginx
Final Iptables rules
[Yaxin@ubox ~] $sudo iptables-nvxl Chain INPUT (Policy ACCEPT 67893 packets, 212661547 bytes) pkts bytes Target Prot opt in Out source destination 14364 790008 DROP TCP--* * 0.0.0.0/0 0.0.0.0/0 TCP dpt:25 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes Target Prot opt in Out source destination 5479682 653269356 Docker All--Docker0 0.0.0.0 /0 0.0.0.0/0 94186 314986910 ACCEPT All--Docker0 0.0.0.0/0-0.0.0.0/0 C
Tstate related,established 4705658 2183254076 ACCEPT All-Docker0!docker0 0.0.0.0/0 0 0 ACCEPT All--Docker0 Docker0 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (Policy-ACCEPT 71253 Packets , 222512872 bytes) pkts bytes Target prot opt in Out source destination Chain ( 1 references) Pkts Bytes Target prot opt in Out source destination 218 13193 ACCEPT TCP--! Docke R0 DOCKER0 0.0.0.0/0 192.168.42.41 tcp dpt:22280 4868186 297463902 ACCEPT TCP--! Docker0 Docker 0 0.0.0.0/0 192.168.42.41 TCP dpt:20280 78663 13128102 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0 /0 192.168.42.41 TCP dpt:22 4321 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0/0 192.168.42.41 TCP dpt:28159 4627 ACCEPT TCP--! Docker0 DOCKER0 0.0.0.0/0 192.168.4 2.43 TCP dpt:8888 [Yaxin@ubox ~] $sudo iptables-t NAT-NVXL Chain prerouting (policy ACCEPT 232 packets, 16606 byte s) pkts bytes target prot opt in Out source destination 1220281 82620790 Docker al L--* * 0.0.0.0/0 0.0.0.0/0 addrtype match Dst-type local Chain INPUT (policy ACCEPT 216 Packets, 15671 bytes) pkts bytes Target prot opt in Out source destination Chain OUTPUT (policy ACCEPT 317 Packets, 19159 bytes) pkts bytes Target prot opt in out source destination 1644 99311 Docker All--* * 0.0.0.0/0!127.0.0.0/8 addrtype match Dst-type local Chain P Ostrouting (Policy ACCEPT 321 packets, 19367 bytes) pkts bytes Target prot opt in Out source Destination 13512 813656 Masquerade All---*!docker0 192.168.42.0/24 0.0.0.0/0 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:22280 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:20280 0 0 Masquerade TCP--* * 192.168.42.41 192.168.42.41 TCP dpt:22 0 0 Masquerade TCP--* * 19 2.168.42.41 192.168.42.41 TCP dpt:28159 0 0 Masquerade TCP--* * 192.168.42.43 192.168.42.43 TCP dpt:8888 Chain Docker (2 references) pkts bytes target prot opt in Out source Destination 1404 Dnat TCP--! DOCKER0 * 0.0.0.0/0 0.0.0.0/0 TCP dpt:22280 to:192.168.42.41:22280 17156 dnat TCP--! Docker0 * 0.0.0.0/0 0.0.0.0/0 t CP dpt:20280 to:192.168.42.41:20280 5952 dnat TCP--! Docker0 * 0.0.0.0/0 0.0.0.0/0 TCP dpt:22222 to:192.168.42.41:22 8 dnat TCP--! Docker0 * 0.0.0.0/0 0 .0.0.0/0 TCP dpt:28159 to:192.168.42.41:28159 4 dnat TCP--! Dokcer0 * 0.0.0.0/0
0.0.0.0/0 TCP dpt:8899 to:192.168.42.43:8888
Of course, using manual configuration is also more cumbersome, so I wrote a script to automatically configure the port mapping, using the method scripts are described in
#!/bin/bash # filename:docker_expose.sh If [' Id-u '-ne 0];then echo ' [Eroor] Please use the ROOT to run this script ' Exit fi if [$#-ne 3];then echo Usage: $ <container_name> <add|del> [[<machine_ip>:]< MACHINE_PORT>:]<CONTAINER_PORT>[/<PROTOCOL_TYPE>] "Exit 1 fi ipv4_re= ' ([0-9]|[ 1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) \.) {3} ([0-9]| [1-9] [0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ' Container_name=$1 action=$2 arguments=$3 # Check action if [' $action ' x!= ' add ' x -A "$action" x!= "del" x];then echo "[ERROR]," Use the Add or del parameter to add port map or delete port map "E Xit 654 fi if ["$action" x = = "Add" x];then action= "A" Else action= "D" FI # Get container IP by container name Co ntainer_ip= ' Docker inspect-f ' {{. Networksettings.ipaddress}} ' $container _name 2>/dev/null ' If [-Z $container _ip];then echo ' [ERROR] Get container ' s (${container_name}) IP error, please ensure to have this container "EXit 2 fi # parse arguments protocol_type= ' echo $arguments | Awk-f '/' {print $} ' if [-Z $protocol _type];then protocol_type= ' tcp ' fi # Check protocol if [' $protocol _type ' x != "TCP" X-a "$protocol _type" x!= "UDP" x];then echo "[ERROR] only TCP/UDP protocol is allowed" exit the fi ma chine_ip= ' machine_port= ' container_port= ' # split the left arguments arguments=${arguments%/*} machine_ip= ' echo $ Arguments | Awk-f ': ' {print $} ' machine_port= ' echo $arguments | Awk-f ': ' {print $} ' container_port= ' echo $arguments | Awk-f ': ' {print $} ' if [-Z $machine _port];then # arguments is:234 container_port= $machine _ip machine_p ort= $machine _ip unset machine_ip elif [z $container _port];then # arguments is:234:456 container_port= $mach Ine_ip machine_port= $machine _port unset machine_ip fi # Check Port number function _check_port_number () {loc Al port_num=$1 if! echo $port _num |
Egrep "^[0-9]+$" &>/dev/null;then echo "[ERROR] Invalid port number $port _num" Exit 3 fi if [$port _num-gt 65535-o $port _num-lt 1 ];then Echo [ERROR] Port number $port _num is out of range (1-56635) "Exit 4 fi} # Check port and IP Address _check_port_number $container _port _check_port_number $machine _port if [!-Z $machine _ip];then if! echo $machine _ip |
Egrep "^${ipv4_re}$" &>/dev/null;then echo "[ERROR] Invalid Ip adress $machine _ip" Exit 5 fi # Check which interface bind the IP for interface in ' Ifconfig-s | Sed-n ' 2, $p ' | awk ' {print} ';d o interface_ip= ' ifconfig $interface | awk '/inet addr/{print substr ($2,6)} ' if ["$interface _ip" x = = "$machine _ip" x];then interface_name=$ Interface break fi do if [z $interface _name];then echo "[ERROR] Can not find int Erface bind with $machine _ip "exit \ Fi Fi # run iptables command echo" [INFO] now StArt to change rules to Iptables "echo" [INFO] changing postrouting chain of NAT table iptables-t Nat-${action} postrout Ing-p ${protocol_type}--dport ${container_port}-S ${container_ip}-D ${container_ip}-j masquerade if [-Z $interface _n Ame];then echo "[INFO] changing Docker chain of filter table" Iptables-${action} Docker! -I docker0-o docker0-p ${protocol_type}--dport ${container_port}-D ${container_ip}-j ACCEPT echo "[INFO] changing Docker chain of NAT table "Iptables-t Nat-${action} Docker!"
-I docker0-p ${protocol_type}--dport ${machine_port}-j dnat--to-destination ${container_ip}:${container_port} else echo "[INFO] changing Docker chain of filter table" Iptables-${action} docker-i $interface _name-o docker0-p ${pro
Tocol_type}--dport ${container_port}-D ${container_ip}-j ACCEPT echo "[INFO] changing Docker chain of NAT table" iptables-t Nat-${action} docker-i $interface _name-p ${protocol_type}--dport ${machine_port}-J Dnat--to-destination ${container_ip}:${container_port} fi