下面进行测试 junit.jar(SpringBoot应用),默认端口 8080,访问
curl 127.0.0.1:8080/hello
返回“Hello World!”
不指定 EXPOSE
》》》需要docker run -p 1234:8080 ...
,进行一次代理,这样访问主机ip:1234
就相当于 访问容器ip:8080
》》》如果不进行代理,主机的1234,8080端口都没有被占用,外部是肯定不能访问的。
》》》外部与容器的网络又是不通的,容器只与主机通信,所以外部就不可以访问容器了。自然需要 -p 进行一层代理。
1 | ------------------------ls |
指定 EXPOSE
》》》使用 -P 会把容器的 EXPOSE 端口 和 主机的一个随机端口进行映射,此时外部访问这个主机的随机端口就相当于访问容器的 EXPOSE 端口了。
》》》若不使用 -P 或 -p 映射端口,那么 EXPOSE 就相当于一个 说明,说明容器哪些端口可用。
1 | ------------------------cat junit |
总结
1、EXPOSE 就相当于 VOLUME 容器卷一样,只是一个声明而已,但 VOLUME 在 docker run 不知道 -v 时,也会使用默认的匿名挂载,但 EXPOSE 声明的端口 则需要docker run 加上 -p(小写) Linux端口:容器端口 来进行映射,或 使用 -P(大写)让 EXPOSE 声明的端口都映射到主机的某一个随机端口上
2、EXPOSE 只是一个声明而已,真正使用是 docker run -p 主机端口:容器端口 或 -P 来指定的。
(一开始我傻乎乎的猜测,只有 EXPOSE 声明的端口,docker run 时才可以使用 -p 指定映射,或 使用 -P 随机映射,事实证明并不是这样)
官方文档
1 | EXPOSE <port> [<port>/<protocol>...] |
该EXPOSE
指令通知Docker容器在运行时监听指定的网络端口。您可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。
该EXPOSE
指令实际上并未发布端口。它充当构建映像的人员和运行容器的人员之间的一种文档类型,有关打算发布哪些端口的信息。要在运行容器时实际发布端口,请使用-p
标记ondocker run
发布和映射一个或多个端口,或者使用-P
标记发布所有公开的端口并将它们映射到高阶端口。
默认情况下,EXPOSE
假定为TCP。您还可以指定UDP:
1 | EXPOSE 80/udp |
要同时在TCP和UDP上公开,请包括以下两行:
1 | EXPOSE 80/tcp |
在这种情况下,如果-P
与配合使用docker run
,则该端口仅对TCP公开一次,对于UDP公开一次。请记住,-P
该端口在主机上使用临时的随机主机端口,因此该端口对于TCP和UDP将是不同的。
无论EXPOSE
设置如何,都可以在运行时使用该-p
标志覆盖它们。例如
1 | docker run -p 80:80/tcp -p 80:80/udp ... |