Docker中“expose”和“publish”有什么区别?

时间:2014-03-01 06:35:53

标签: docker

我正在尝试使用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中公开端口有什么意义,如果它仍然会被发布?是否需要首先公开端口,以后发布它?实际上,我想在创建映像时指定我将在Dockerfile中使用的所有端口,然后再不用再次打扰它们,只需运行它们:

$ docker run -d an_image

这可能吗?

7 个答案:

答案 0 :(得分:576)

基本上,您有三种选择:

  1. 既未指定EXPOSE也未指定-p
  2. 仅指定EXPOSE
  3. 指定EXPOSE-p
  4. 1)如果您既未指定EXPOSE也未指定-p,则只能从 容器本身访问容器中的服务。

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

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

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

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

    documentation明确指出:

      

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

    它还指出如何link containers,这主要是我所谈到的容器间通信。

    PS:如果您执行-p但不EXPOSE,则Docker会执行隐式EXPOSE。这是因为如果一个端口对公众开放,它也会自动向其他Docker容器开放。因此-p包含EXPOSE。这就是为什么我没有把它作为第四种情况列在上面。

答案 1 :(得分:80)

简答:

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

请注意以下内容:

  • EXPOSEDockerfiles记录
  • 相关
  • --publishdocker run ...执行/运行时
  • 相关
  

公开和发布端口

     

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

     
      
  • 使用Dockerfile中的EXPOSE关键字或--expose标志将端口暴露给docker run。 公开端口是记录使用哪些端口的方法,但实际上并未映射或打开任何端口。公开端口是可选的

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

  •   
     

来自:Docker container networking

此外,

  

EXPOSE

     

... EXPOSE指令实际上并未发布端口。 它可以作为构建图像的人和运行容器的人之间的一种文档,关于哪些端口要发布

     

来自:Dockerfile reference





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

@Golo Roden's回答时声明::

  

&#34;如果您未指定其中任何一项,将无法从容器内部的任何位置访问容器中的服务。&#34;

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

如何测试:

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

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

build图片为&#34; testexpose&#34;和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的主页。

答案 2 :(得分:7)

EXPOSE允许您定义私有(容器)和公共(主机)端口,以便在映像构建时公开容器运行的时间。 公共端口是可选的,如果没有指定公共端口,则docker将在主机上选择一个随机端口,以在Dockerfile上公开指定的容器端口。

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

您可以使用-p中的docker run来控制公开端口可以连接的公共端口。

无论如何,如果您不使用EXPOSE-p,则不会暴露任何端口。

如果您始终在-p使用docker run,则不需要EXPOSE,但如果您使用EXPOSE,则docker run命令可能会更简单,{{ 1}}如果您不关心将在主机上公开的端口,或者您确定只加载一个容器,则非常有用。

答案 3 :(得分:3)

大多数人使用docker compose with networks。 documentation州:

  

Docker网络功能支持创建网络而无需在网络中公开端口,详细信息请参阅此功能的概述。

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

答案 4 :(得分:3)

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

来源:github commit

答案 5 :(得分:0)

Dockerfile EXPOSE与发布

曝光

在编写Dockerfile时,指令EXPOSE告诉Docker运行中的容器在特定的网络端口上进行侦听。这是一种端口映射文档,可在发布端口时使用。

曝光[/...]

您还可以在docker run命令中指定此名称,例如:

docker run --expose = 1234 my_app

但是EXPOSE不允许通过定义的端口与同一网络外部的容器或主机进行通信。为此,您需要发布端口。

发布端口并将其映射到主机

使用docker run命令在容器网络外部发布容器的端口并将其映射到主机的端口时,可以使用多个标志。这些是-p和-P标志,它们在您要发布一个端口还是所有端口方面有所不同。

要在运行容器时实际发布端口,请在docker run上使用-p标志发布并映射一个或多个端口,或使用-P标志发布所有公开的端口并将其映射到高阶端口。 — Docker文档:EXPOSE

docker run -p 80:80 / tcp -p 80:80 / udp my_app

在上面的示例中,-p标志后面的第一个数字是主机端口,第二个是容器端口。

要使用EXPOSE发布您在Dockerfile中定义的所有端口并将其绑定到主机,可以使用-P标志。

docker run -P my_app

答案 6 :(得分:-3)

EXPOSE用于映射本地端口容器端口 即:如果您在

之类的docker文件中指定暴露

EXPOSE 8090

它将做什么,它将本地主机端口8090映射到容器端口8090