Docker中"expose"和"publish"有什么区别?

use*_*984 453 docker

我正在尝试使用Dockerfiles,我想我理解大部分逻辑.但是,我没有看到在这种情况下"暴露"和"发布"端口之间的区别.

我首先看到的所有教程都包含EXPOSEDockerfile中的命令:

...
EXPOSE 8080
...
Run Code Online (Sandbox Code Playgroud)

然后他们从这个Dockerfile构建一个图像:

$ docker build -t an_image - < Dockerfile
Run Code Online (Sandbox Code Playgroud)

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

$ docker run -d -p 8080 an_image
Run Code Online (Sandbox Code Playgroud)

或使用发布所有端口

$ docker run -d -P an_image
Run Code Online (Sandbox Code Playgroud)

暴露Dockerfile中的端口有什么意义,如果它仍然会被发布?是否需要首先公开一个端口,而不是稍后发布它?实际上,我想在创建映像时指定我将在Dockerfile中使用的所有端口,然后再不打扰它们,只需运行它们:

$ docker run -d an_image
Run Code Online (Sandbox Code Playgroud)

这可能吗?

Gol*_*den 659

基本上,您有三种选择:

  1. 既没有指明EXPOSE也没有-p
  2. 只指定 EXPOSE
  3. 指定EXPOSE-p

1)如果您既未指定EXPOSEnor -p,则只能从容器内部访问容器中的服务.

2)如果你EXPOSE是一个端口,容器中的服务不能从Docker外部访问,而是从其他Docker容器内部访问.所以这对于容器间通信很有用.

3)如果你EXPOSE-p一个端口,容器中的服务可以从任何地方访问,甚至可以在Docker外部访问.

两者分开的原因是恕我直言,因为:

  • 选择主机端口取决于主机,因此不属于Dockerfile(否则它将取决于主机),
  • 如果容器中的服务可以从其他容器访问,通常就足够了.

文件明确规定:

EXPOSE指令公开了在链接中使用的端口.

它还指出了如何链接容器,这基本上是我所谈到的容器间通信.

PS:如果你这样做-p,但不这样做EXPOSE,Docker会暗示EXPOSE.这是因为如果一个端口对公众开放,它也会自动向其他Docker容器开放.因此-p包括EXPOSE.这就是为什么我没有把它作为第四种情况列在上面.

  • 我认为你对EXPOSE不正确.从其他容器中,您可以访问所有容器端口而不会暴露它们.我试过了.这里的问题是容器IP地址是不可预测的.我相信链接用于指定您要连接的容器(因此您链接到特定的容器IP),而不是启用连接. (51认同)
  • "如果你没有指定其中的任何一个",如果你用"那些"来澄清你的意思是"EXPOSE"和`-p`而不是前面的三个子弹点,那将会很有用.让我困惑了一下. (6认同)
  • 文档不再声明"EXPOSE指令公开了在链接中使用的端口". (5认同)
  • Downvote,因为这是非常不正确的.Expose基本上是文档,不使用它不会限制访问.如果有人依赖它来限制访问,这是一个危险的误解. (5认同)
  • 要完全完成,这个答案还应该解决第四种可能的情况:你没有指定`EXPOSE`,但你*确定*指定`-p`.我的理解是,如果你总是使用`-p`并运行单独的容器,那么`EXPOSE`可以省略,但在使用`-P`或`--link`时它变得有用/必要.(并且由于您不知道其他人将如何使用您的图像,因此应在任何公共图像中指定"EXPOSE".) (4认同)
  • 看来你的答案已经过时了.编辑答案以指出这一事实可能会有所帮助,并链接到下面的@tgogos答案(在撰写本评论时),链接:/sf/ask/1547774231/ /差之间展露-和发布功能于泊坞窗47594352#47594352 (4认同)
  • 是的,@ jiri是对的.我认为当容器被其他人链接时,EXPOSE指令的含义由docker自动设置环境变量,其他人可以通过变量访问容器. (3认同)
  • 确切地说:你不能。这样做的原因是您事先不知道主机上还会运行什么,因此对其进行硬编码没有任何意义。 (2认同)

tgo*_*gos 124

简短回答:

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

请注意以下内容:

  • EXPOSEDockerfiles(记录)有关
  • --publishdocker run ...(执行/运行时)有关

公开和发布端口

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

  • 您使用EXPOSEDockerfile中的关键字或docker --exposerun标志公开端口.公开端口是记录使用哪些端口但实际上不映射或打开任何端口的方法.公开端口是可选的.

  • 您使用--publish--publish-all标记来发布端口docker run.这告诉Docker在容器的网络接口上打开哪些端口.发布端口时,它将映射到30000主机上可用的高位端口(高于),除非您在运行时指定要在主机上映射到的端口.在构建映像时(在Dockerfile中),无法指定要在主机上映射到的端口,因为无法保证端口在运行映像的主机上可用.

来自:Docker容器网络

也,

暴露

... --publish指令实际上没有发布端口.它在构建映像的人和运行容器的人之间起到一种文档的作用,关于哪些端口要发布.

from:Dockerfile引用






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

@Golo Roden的回答中说明::

"如果你没有指定任何一个,那么容器中的服务将无法从容器内部的任何地方访问."

也许这是在答案被写入时的情况,但现在看来,即使你不使用EXPOSE或者--publish,EXPOSE和其他--publish同网络将能够访问你可能是容器内启动服务.

如何测试:

我使用了以下内容host.基本上,我从ubuntu开始并安装一个小型的Web服务器:

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
Run Code Online (Sandbox Code Playgroud)

containers将图像作为"testexpose"和Dockerfile一个新容器:

docker run --rm -it testexpose bash
Run Code Online (Sandbox Code Playgroud)

在容器内部,我启动了几个实例build:

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090
Run Code Online (Sandbox Code Playgroud)

然后我可以使用run主机或其他容器来获取主页mini-httpd.

  • 这是现在正确的答案.似乎已接受答案是基于先前的版本. (10认同)
  • “EXPOSE”确实做了一些事情,而不仅仅是文档。如果您使用“-P”标志“运行”,它将发布““所有暴露的端口到随机端口”。 (4认同)

mza*_*zar 8

您可以使用 Dockerfile 中的 EXPOSE 关键字或 --expose 标志向 docker run 公开端口。公开端口是一种记录使用了哪些端口的方式,但实际上并不映射或打开任何端口。暴露端口是可选的。

来源:github提交

  • 我认为措辞选择不当?如果只是记录,他们可能会选择......我不知道,除了暴露哈哈。 (2认同)

ton*_*ton 7

EXPOSE允许你定义私有(容器)和公共(主机)端口,在图像生成时揭露,容器运行时.公共端口是可选的,如果未指定公共端口,则docker将在主机上选择随机端口以在Dockerfile上公开指定的容器端口.

一个好的实践是不指定公共端口,因为它每个主机只限制一个容器(第二个容器将抛出已经在使用的端口).

您可以使用-pin docker run来控制暴露的容器端口可连接的公共端口.

无论如何,如果你不使用EXPOSE-p不会暴露任何端口.

如果你总是使用-pdocker run你不需要EXPOSE,但如果你用EXPOSE你的docker run命令可能会更简单,EXPOSE如果你不关心什么端口将主机被暴露,或者如果你确信只有一个容器将被加载是有用的.


her*_*erm 5

大多数人使用 docker compose 与网络。该文件指出:

Docker 网络功能支持创建网络而无需暴露网络内的端口,有关详细信息,请参阅此功能的概述)。

这意味着如果您使用网络在容器之间进行通信,则无需担心暴露端口。


归档时间:

查看次数:

169867 次

最近记录:

6 年 前