0. 概述

在使用 Docker 的时候,因为一般都是运行应用程序在容器中,所以如何访问容器内的应用程序成了问题,一个比较常见的操作就是将容器内的应用端口暴露出来,让外部可以访问。

这里就有一些问题了,就是端口要如何暴露?Docker 的端口暴露需要两部分配合,一个是 Dockerfile 声明(非必须),另外一个是运行 Docker 镜像的时候进行命令指定。下面就根据个人的经验介绍 3 种暴露服务端口的方法。

1. Image 暴露端口

虽然在 Dockerfile 中指定端口不是一个必须的事情,但是,这对于一个 Image 来说是个好习惯,可以让别人快速知道应用的端口,同时,也方便直接暴露应用的端口(方法2使用),在 Dockerfile 中指定暴露端口很简单:代码示例

  1. [[email protected].io]# cat Dockerfile
  2. ....
  3. EXPOSE 80
  4. ENTRYPOINT ["/rest-server"]
  5. ....

这样就对外宣称了我这个 Image 在内部会使用 80 端口,要怎么暴露你们看着办。

2. 暴露端口

2.1 -p 参数

在 docker run 中有个 -p 参数,可以指定本地的哪个端口映射 Container 中的端口,形式为:

  1. [[email protected].io]# docker run -p 8080:80

这里就表示我本机的 8080 端口映射 Container 中的 80 端口,只要访问 localhost:8080 就能够访问到 Container 中的 80。需要注意的是,这个 8080 是对于所有的网络接口都会生效,如果想绑定网卡的话,可以指定 IP:

  1. [[email protected].io]# docker run -p 10.0.0.9:8080:80

这样,就只能使用本地的子网 10.0.0.9:8080 才能访问 Container 了,就连 localhost:8080 都访问不通了。

2.2 -P 参数

如果嫌弃要用 -p 一个一个得指定端口太麻烦,那么可以试一下大写得字母 P,他可以不用指定参数,根据 Image 的描述直接帮你暴露一个随机端口,例如:

  1. [[email protected].io]# docker run --rm -d -P mongo:4.1
  2. [[email protected].io]# docker ps
  3. 5d6a756e3e5c mongo:4.1 "docker-entrypoint.s…" 6 seconds ago Up 4 seconds 0.0.0.0:32768->27017/tcp admiring_austin

这里就给我分配了 32768 这个端口用于映射容器中的应用端口。

2.3 主机网络

还有一种方式,不用映射端口,直接让容器使用我本机的网络,这样,容器内部绑定什么端口,就相当于在我本机绑定了什么端口,例如:

  1. [[email protected].io]# docker run --rm -d --net=host nginx:1.17.0
  2. [[email protected].io]# ss -anlp | grep 80
  3. tcp LISTEN 0 128 *:80 *:* users:(("nginx",pid=28978,fd=6),("nginx",pid=28945,fd=6))

3. 小结

这就是我关于 Docker 端口的一些总结了。一般来说,用小写的 p 参数比较多,因为更具体一些;但是,在一些情况下也会用 hostnetwork,例如你想要让你的容器内的应用访问主机的应用服务的时候,通过使用主机网络就会很方便了。