问题描述

docker自身是有一个网络系统的,对于一个运行在docker内的程序的某个端口(比如training/webapp这个镜像下的flask的5000端口)。如果要进行访问,详细的过程是:

  1. 访问服务器的ip:port
  2. 公网ip:port --> docker的ip:port
  3. 通过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查看,PORTS0.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

但是阿里云服务器有防火墙,默认只开放了2280443三个端口。

因此-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

  1. docker端口映射
  2. Docker 从入门到实践
  3. 菜鸟教程
  4. Docker 网络-端口映射、容器链接、Networking