Docker中的Expose和Publish有什么区别?

xxhby3vn  于 2022-10-23  发布在  Docker
关注(0)|答案(7)|浏览(526)

我正在试验DockerFiles,我想我理解其中的大部分逻辑。然而,在这种情况下,我看不出“公开”和“发布”端口之间的区别。
我第一次看到的所有教程都包含Dockerfile中的EXPOSE命令:

...
EXPOSE 8080
...

然后,他们从该Dockerfile构建一个映像:

$ docker build -t an_image - < Dockerfile

然后在运行镜像时发布与上面相同的端口:

$ docker run -d -p 8080 an_image

或使用发布所有端口

$ docker run -d -P an_image

如果某个端口无论如何都要发布,那么在Dockerfile中公开它有什么意义呢?有没有必要先公开一个端口,然后“不”再发布它?实际上,我希望指定在创建映像时将在Docker文件中使用的所有端口,然后不再使用它们,只需使用以下命令运行它们:

$ docker run -d an_image

这个是可能的吗?

i2byvkas

i2byvkas1#

基本上,您有三(四)个选项:
1.既不指定EXPOSE,也不指定-p
1.仅指定EXPOSE
1.指定EXPOSE-p
1.仅指定隐式执行EXPOSE-p
1.如果不指定EXPOSE,也不指定-p,则容器中的服务只能从容器本身的内部访问。
1.如果您EXPOSE一个端口,则容器中的服务不能从Docker外部访问,而是从其他Docker容器内部访问。因此,这对于集装箱之间的通信是有好处的。
1.如果您的EXPOSE-p是一个端口,则容器中的服务可以从任何地方访问,即使是在Docker之外。
1.如果您做了-p,但不做EXPOSE,Docker会隐式做EXPOSE。这是因为如果一个港口对公众开放,它也会自动对其他Docker容器开放。因此,-p包括EXPOSE。这实际上与3)相同。
两者分离的原因是因为:

  • 主机端口的选择取决于主机,因此不属于Docker文件(否则将取决于主机),
  • 通常情况下,容器中的服务可以从其他容器访问就足够了。

该文档明确规定:
EXPOSE指令公开链接内使用的端口。
它还为您指明了如何使用link containers,这基本上就是我所说的容器间通信。

svujldwt

svujldwt2#

简答:

  • EXPOSE是一种记录的方式
  • --publish(或-p)是Map一个主机端口到一个正在运行的容器端口的一种方式

请注意以下内容:

  • EXPOSEDockerfiles相关(文档中)
  • --publishdocker run ...(执行/运行时)相关

暴露和发布端口

在Docker网络中,有两种不同的机制直接涉及网络端口:暴露端口和发布端口。这适用于默认网桥网络和用户定义的网桥网络。

  • 使用Dockerfile中的EXPOSE关键字或--expose标志公开端口以停靠运行。暴露端口是一种记录使用了哪些端口的方式,但不会实际Map或打开任何端口。暴露端口是可选的。
  • 使用--publish--publish-all标志将端口发布到docker run。这将告诉Docker在容器的网络接口上打开哪些端口。发布端口时,它将Map到主机上可用的高阶端口(高于30000),除非您在运行时在主机上指定要Map到的端口。您无法在构建镜像时指定要Map到宿主机上的端口(在Dockerfile中),因为无法保证该端口在您运行镜像的宿主机上可用

出发地:码头集装箱网络

2019年10月更新:文档中不再有上述文本,但存档版本在此处:docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports

也许当前的文档如下所示:

发布的端口

默认情况下,当您创建容器时,它不会向外部世界发布其任何端口。要使端口可用于Docker外部的服务或未连接到容器网络的Docker容器,请使用--publish-p标志。这将创建将容器端口Map到Docker主机上的端口的防火墙规则。
并可在此处找到:docs.docker.com/config/containers/container-networking/#published-ports
另外,

曝光

...EXPOSE指令实际上并不发布端口。它的作用是构建镜像的人和运行容器的人之间的一种文档,关于打算发布哪些端口。
发件人:Dockerfile参考

未定义EXPOSE/--publish时的服务访问:

在@Golo Roden的回答中说::

  • “如果您不指定其中的任何一项,则容器中的服务将无法从任何位置访问,除非从容器本身内部。”*

也许在编写答案时是这样的,但现在看来,即使您不使用EXPOSE--publish,同一网络的host和其他containers也将能够访问您可能在该容器内启动的服务。

如何测试:

我使用了以下Dockerfile。基本上,我从ubuntu开始,然后安装一个小型Web服务器:

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd

I build图像为“Testexposure”,run为新容器,带有:

docker run --rm -it testexpose bash

在容器中,我启动了几个mini-httpd示例:

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090

然后,我可以从主机或其他容器使用curl来获取mini-httpd的主页。

进一步阅读

Ivan Pepelnjak关于这个主题的非常详细的文章:

ffvjumwh

ffvjumwh3#

请参阅官方文档参考:https://docs.docker.com/engine/reference/builder/#expose
EXPOSE允许您定义私有(容器)和公共(主机)端口,以便在映像构建时暴露容器运行时*如果**您使用-P运行容器。

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

公共端口和协议是可选的,如果不指定公共端口,docker会在host上随机选择一个端口,在Dockerfile上暴露指定的容器端口。
一个不错的做法是不要指定公共端口,因为它只限制每个主机一个容器(第二个容器将抛出一个已在使用的端口)。
您可以在docker run中使用-p来控制公开的容器端口将连接到哪个公共端口。
无论如何,如果您不使用EXPOSE(在docker run上使用-P),也不使用-p,则不会暴露任何端口。
如果您总是在docker run上使用-p,则不需要EXPOSE,但如果您使用EXPOSE,则docker run命令可能会更简单,如果您不关心主机上将公开哪个端口,或者如果您确定只加载一个容器,则EXPOSE可能会很有用。

iyfamqjs

iyfamqjs4#

您可以使用Dockerfile中的expose关键字或--expose标志公开端口以运行docker。公开端口是记录使用了哪些端口的一种方式,但实际上并不Map或打开任何端口。暴露端口是可选的。
来源:GitHub提交

tv6aics1

tv6aics15#

大多数人使用对接式作文与网络。文档说明:
Docker网络功能支持创建网络,无需暴露网络内的端口,详细信息请参见该功能的概述)。
这意味着,如果您使用网络在容器之间进行通信,则不需要担心暴露端口。

8hhllhi2

8hhllhi26#

Exposed关键字让所有者通知其他人容器主要使用哪些端口。
您可以发布任何端口,即使您没有在Exposure中指定端口。
例如,我们使用nginx图像创建了一个Dockerfile,该文件公开了端口1234

FROM nginx:latest
EXPOSE 1234

并建造它
Docker Build-t端口测试。
并使用发布80端口到本地主机:80来运行它
Docker Run-p 80:80端口测试
当您转到Localhost:80时,您将看到nginx默认页面。Nginx default page

r6l8ljro

r6l8ljro7#

Expose用于Map本地端口容器端口ie:如果您在如下所示的docker文件中指定expose
EXPOSE 8090
它将执行什么操作将本地主机端口8090Map到容器端口8090

相关问题