问题描述
docker自身是有一个网络系统的,对于一个运行在docker内的程序的某个端口(比如training/webapp这个镜像下的flask的5000端口)。如果要进行访问,详细的过程是:
- 访问服务器的ip:port
- 公网ip:port --> docker的ip:port
- 通过docker的ip:port连接到某个api服务
总共有三层逻辑:服务器层、容器层、应用层。
最终计算请求数据的是容器内的应用,但是这个应用的端口是无法在公网上查看的,这就需要使用docker的端口映射功能。
端口映射
docker默认是不对外开放端口的。
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。
所以如果在容器内运行网络应用和服务是无法提供给外界使用的,端口映射功能可以实现公网上访问容器内部的网络应用。
-p 可以指定要映射的端口,并且在一个指定端口上只可以绑定一个容器
-P 随机映射一个主机端口(这个是随机的)到容器内部开放的网络端口(这个端口是程序设定的)
“映射”这个概念,是从外向内;是指将外网中访问的port映射到容器内部的port上。
支持格式:
# 绑定宿主机IP及端口,服务器主机上可能有多快网卡
ip:hostPort:containerPort
# 绑定宿主机IP
ip::containerPort
# 绑定宿主机端口
hostPort:containerPort
案例
在阿里云ubuntu16.04
系统上运行菜鸟教程中给出的training/webapp
案例。
docker run -P
docker run -d -P training/webapp python app.py
通过docker -ps
查看,PORTS
为0.0.0.0:32769->5000/tcp。
这个端口信息的意思是:
- 外界所有ip地址(0.0.0.0)
- 都可以访问本服务器的32769端口(本服务器公网47.240.xx.xx),即访问47.240.xx.xx:32769
- 就相当于访问training/webapp容器中的app.py程序所开放的5000端口
docker run -p
runoob@runoob:~$ docker run -d -p 80:5000 training/webapp python app.py
但是阿里云服务器有防火墙,默认只开放了22、80、443三个端口。
因此-P
默认映射的32769端口是无效的,用-p
将容器内5000端口映射为主机服务器上的80端口方可有效。
当然,开放服务器的32769也是一个道理。
此时访问47.240.xx.xx:80
就可以得到 Hello world!。
-p 可以多次使用指定多个端口映射
docker run -p 80:5000 -p 443:5100 training/webapp python app.py
Docker进行端口绑定时,默认会绑定TCP端口。还可以使用udp标记来绑定udp端口:
sudo docker run -d --name experss-app -p 3000:3000/udp itbilu/express-app
docker port id/name
>>> docker port container_id
# or
>>> docker port container_name
5000/tcp -> 0.0.0.0:80
查看指定容器的端口映射。
References