端口映射的方式都好几种,但是动态端口映射却很少(尽管搜索出来一大堆,但都需要重启docker)
吐槽
比如这个网友(标题是如何动态修改docker的端口映射),看标题觉得没问题,再看文章简直要气死,忽悠人。
还好经过不停的努力百度,Google还是找到了好心人。
docker动态映射运行的container端口
具体如下:
1. 在容器中启动服务 (在docker容器内执行)
app8200.py
代码:
import os
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
provider = str(os.environ.get('PROVIDER', 'world'))
print('hello world')
return 'Hello '+provider+'!'
@app.route('/say/<name>')
def say(name):
print('Hi '+name)
return 'Hi ' + name;
if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 5000.
port = int(os.environ.get('PORT', 8200))
app.run(host='0.0.0.0', port=port)
以上代码源自镜像 training/webapp
。拉取,启动如下(参考菜鸟教程 - 运行一个 web 应用):
runoob@runoob:~# docker pull training/webapp # 载入镜像
runoob@runoob:~# docker run -d -P training/webapp python app.py
后台启动:
# 后台启动
root@f015d8bfde1f:/opt/webapp# python app8200.py > 8200.log &
# 查看端口,确认下。8200端口确认启动
root@f015d8bfde1f:/opt/webapp# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:8200 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN
2. 端口映射 (在宿主机执行,外部机器执行)
将容器中8200端口映射到本机8201端口
# 先查下容器以后端口
power@power-java:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f015d8bfde1f skyjilygao/ubuntu:v1 "python app.py" 42 hours ago Up 16 minutes 80/tcp, 0.0.0.0:8001->8001/tcp, 0.0.0.0:2222->22/tcp, 0.0.0.0:5001->5000/tcp eager_bhaskara
power@power-java:~$
# 查看容器ip,也可以进到容器内使用 `ifconfig` 查看
power@power-java:~$ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' f015d8bfde1f
172.17.0.2
power@power-java:~$
power@power-java:~$
# 以下3条端口映射命令是关键。将容器中8200端口映射到本机8201端口
power@power-java:~$ sudo iptables -A DOCKER ! -i docker0 -o docker0 -p tcp --dport 8200 -d 172.17.0.2 -j ACCEPT
power@power-java:~$ sudo iptables -t nat -A POSTROUTING -p tcp --dport 8200 -s 172.17.0.2 -d 172.17.0.2 -j MASQUERADE
power@power-java:~$ sudo iptables -t nat -A DOCKER ! -i dokcer0 -p tcp --dport 8201 -j DNAT --to-destination 172.17.0.2:8200
关键命令:
sudo iptables -A DOCKER ! -i docker0 -o docker0 -p tcp --dport 8200 -d 172.17.0.2 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -p tcp --dport 8200 -s 172.17.0.2 -d 172.17.0.2 -j MASQUERADE
sudo iptables -t nat -A DOCKER ! -i dokcer0 -p tcp --dport 8201 -j DNAT --to-destination 172.17.0.2:8200
3. 使用 iptables
查看端口映射关系:
sudo iptables -t nat -nvL
power@power-java:~$ sudo iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 2121 packets, 179K bytes)
pkts bytes target prot opt in out source destination
3 156 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8004 to:172.17.0.2:6379
28 1456 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8005 to:172.17.0.2:8001
128 6734 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 649 packets, 100K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 2 packets, 152 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 9 packets, 516 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:8001
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:5000
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:22
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:8100
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:8200
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
7 364 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8006 to:172.17.0.2:8001
51 2652 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8101 to:172.17.0.2:8100
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8001 to:172.17.0.2:8001
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5001 to:172.17.0.2:5000
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2222 to:172.17.0.2:22
3 156 DNAT tcp -- !dokcer0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8102 to:172.17.0.2:8100
7 364 DNAT tcp -- !dokcer0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8201 to:172.17.0.2:8200
power@power-java:~$
4. 从其他机器执行 telnet
再次确认端口是否映射成功。
我这里宿主机ip是 192.168.88.23
我从另一台windows机器 连 宿主机,在 cmd 执行telnet
PS C:\Users\Administrator> telnet 192.168.88.23 8201
没问题,能通。
5. 访问 http://192.168.88.23:8201/say/66666666
成功访问,至此,真正的动态端口映射已经完成。
妈妈再也不通担心重启docker了。
推广:个人Github