我首先看到的所有教程都在Dockerfile中包括
EXPOSE
命令:然后他们从这个Dockerfile构建映像:
...
EXPOSE 8080
...
,然后在运行时发布与上述相同的端口图像:
$ docker build -t an_image - < Dockerfile
或使用
发布所有端口
$ docker run -d -p 8080 an_image
在端口中公开端口的意义是什么Dockerfile,是否仍要发布?是否需要先公开一个端口,然后再不发布它?实际上,我想在创建映像时指定要在Dockerfile中使用的所有端口,然后不再麻烦它们,只需使用以下命令即可运行它们:
$ docker run -d -P an_image
这可能吗?
#1 楼
基本上,您有三个选择:既不指定
EXPOSE
也不指定-p
仅指定
EXPOSE
指定
EXPOSE
和-p
1)如果您既未指定
EXPOSE
也未指定-p
,则只能从容器本身内部访问容器中的服务。2)如果您通过
EXPOSE
端口,不能从Docker外部访问容器中的服务,而可以从其他Docker容器内部访问容器中的服务。 3)如果将
EXPOSE
和-p
用作端口,则可以从任何地方访问容器中的服务,甚至可以从Docker外部访问。两者分开的原因是恕我直言,因为:
选择主机端口取决于主机,因此不属于Dockerfile(否则取决于主机),
并且通常可以从其他容器访问容器中的服务。
文档中明确指出:
EXPOSE
指令公开了以下端口在链接内使用。它还为您提供了链接容器的方法,这基本上就是我所说的容器间通信。
PS:如果您做
-p
而不做EXPOSE
,Docker做一个隐式EXPOSE
。这是因为如果某个端口向公众开放,那么它也会自动向其他Docker容器开放。因此,-p
包括EXPOSE
。这就是为什么我没有在上面将其列为第四种情况。#2 楼
简短的答案:EXPOSE
是一种记录方式--publish
(或-p
)是一种将主机端口映射到正在运行的容器的方式端口下面的注意事项:
EXPOSE
与Dockerfiles
相关(记录)--publish
与docker run ...
(执行/运行时)相关。公开和发布端口
在Docker网络中,有两种直接涉及网络端口的不同机制:公开和发布端口。这适用于默认的桥接网络和用户定义的桥接网络。
使用Dockerfile中的
EXPOSE
关键字或--expose
标志向docker run公开端口。公开端口是一种记录使用哪些端口的方式,但实际上并没有映射或打开任何端口。公开端口是可选的。使用
--publish
或--publish-all
标志发布端口至docker run
。这告诉Docker在容器的网络接口上打开哪些端口。发布端口后,除非您在运行时指定要映射到主机上的端口,否则它将映射到主机上可用的高阶端口(高于30000
)。生成映像时(在Dockerfile中),您无法指定要映射到主机上的端口,因为无法保证端口在运行映像的主机上将可用。来自:Docker容器网络
2019年10月更新:上面的文本不再在docs中,而是此处的存档版本:docs.docker.com/v17.09/engine / userguide / networking /#exposed-and-publishing-ports
当前文档可能如下:
已发布的端口
默认情况下,创建容器时,它不会将其任何端口发布到外界。要使端口可用于Docker外部的服务或未连接到容器网络的Docker容器,请使用
--publish
或-p
标志。这将创建一个防火墙规则,该规则将容器端口映射到Docker主机上的端口。,可以在以下位置找到:docs.docker.com/config/containers/container-networking/#published-ports
此外,
EXPOSE
...
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
我将
build
的图像显示为“ testexpose”,并将一个新的容器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关于该主题的非常详尽的文章:
暴露的端口
已发布的端口
评论
现在这是正确的答案。似乎,接受的答案基于先前的版本。
–卢克W
18年1月16日在20:57
EXPOSE实际上确实在做一些事情,而不仅仅是文档。如果使用-P标志运行,它将发布“所有公开的端口到随机端口”。
– papiro
7月21日4:30
#3 楼
请参阅官方文档参考:https://docs.docker.com/engine/reference/builder/#exposeEXPOSE
允许您定义私有(容器)和公共(主机)端口以公开如果使用-P
运行容器,则在运行容器时在映像生成时。$ docker help run
...
-P, --publish-all Publish all exposed ports to random ports
...
如果未指定公共端口,则公共端口和协议是可选的,则docker将在主机上选择一个随机端口以在Dockerfile上公开指定的容器端口。
不指定公共端口是一个好习惯,因为它限制了每个主机一个容器(第二个容器)将会抛出一个已经在使用的端口)。
您可以在
-p
中使用docker run
来控制暴露的容器端口可以连接的公共端口。无论如何,如果您不使用
EXPOSE
(在docker run上使用-P
)或-p
,不会暴露任何端口。如果始终在
-p
上使用docker run
,则不需要q43 12079q,但是如果您使用EXPOSE
,则您的EXPOSE
命令可能会更简单,如果您不在乎主机上将公开哪个端口,或者确定只能加载一个容器,则docker run
可能会很有用。评论
这是对的。当Dockerfile中有EXPOSE端口号时,请记住调用以-P运行的docker。
–蔡坤宇
4月15日9:04
#4 楼
您可以使用Dockerfile中的EXPOSE关键字或--expose标志将端口公开给docker run。公开端口是一种记录使用了哪些端口的方法,但实际上并没有映射或打开任何端口。暴露端口
是可选的。
来源:github commit
评论
imo措辞选择不佳?如果只是记录,他们可以选择...我不知道,但是任何东西都会大声笑。
–dtc
12月4日,0:07
#5 楼
大多数人将docker与网络结合使用。文档指出:Docker网络功能支持创建网络,而无需暴露网络中的端口,有关详细信息,请参阅此功能的概述。)
这意味着,如果您使用网络在容器之间进行通信,则无需担心暴露端口。
#6 楼
EXPOSE用于映射本地端口容器端口即:如果您在docker文件中指定暴露,例如
EXPOSE 8090
它将做什么,它将本地主机端口8090映射到集装箱港口8090
评论
我认为您对EXPOSE的看法不正确。从其他容器,您可以访问所有容器端口而无需暴露它们。我试过了这里的问题是容器IP地址是不可预测的。我相信该链接用于指定您要连接的容器(因此您链接到特定的容器IP),而不是启用连接。
–吉里
2014年4月4日5:45
“如果您未指定任何一个”,如果您明确指出“那些”是指EXPOSE和-p,而不是前面的三个要点,将很有用。让我有点困惑。
– Pithikos
2014年8月8日在9:24
docs不再声明“ EXPOSE指令公开了供链接使用的端口”。
–罗琳·霍希斯坦(Lorin Hochstein)
17年2月4日在6:57
下注,因为这基本上是不正确的。公开基本上是文档,不使用它并不限制访问。如果有人依靠它来限制访问权限,这是一个扎堆的误解。
–mc0e
18年7月31日在2:21
您的答案似乎过时了。编辑答案以指出这一事实并链接到下面的@tgogos答案(在撰写此评论时)可能会有所帮助,链接:stackoverflow.com/questions/22111060 / ...
–全能骆驼Moha
18年11月21日在15:11