Docker中的”公开”和”发布”有什么区别? “expose” and “publish”

What is the difference between “expose” and “publish” in Docker?

我正在试验dockerfiles,我想我理解大部分逻辑。但是,在这个上下文中,我看不到"公开"和"发布"端口之间的区别。

我首先看到的所有教程都包括dockerfile中的EXPOSE命令:

1
2
3
...
EXPOSE 8080
...

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

1
$ docker build -t an_image - < Dockerfile

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

1
$ docker run -d -p 8080 an_image

或使用发布所有端口

1
$ docker run -d -P an_image

如果要发布Dockerfile中的端口,那么在Dockerfile中公开端口有什么意义?有没有必要先公开一个端口,以后再发布它?实际上,我想指定创建映像时将在dockerfile中使用的所有端口,然后不再麻烦它们,只需运行它们:

1
$ docker run -d an_image

这有可能吗?


基本上,您有三种选择:

  • 既不指定EXPOSE也不指定-p
  • 仅指定EXPOSE
  • 指定EXPOSE-p
  • 1)如果您既没有指定EXPOSE也没有指定-p,则只能从容器内部访问容器中的服务。

    2)如果您使用的是cx1〔0〕一个港口,那么集装箱内的服务不能从码头外进入,而是从其他码头集装箱内进入。所以这对于容器间的通信是很好的。

    3)如果您是EXPOSE-p一个港口,集装箱内的服务可以从任何地方,甚至在码头外访问。

    二者分开的原因是imho,因为:

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

    文件明确规定:

    The EXPOSE instruction exposes ports for use within links.

    它还向您指出了如何链接容器,这基本上就是我所讨论的容器间通信。

    附言:如果你做-p,但不做EXPOSE,docker会做一个隐含的EXPOSE。这是因为如果一个港口向公众开放,它也会自动向其他码头集装箱开放。因此,-p包括EXPOSE。所以我没有把它列为第四个案例。


    简短回答:

    • EXPOSE是一种记录
    • --publish-p是将主机端口映射到正在运行的容器端口的一种方法。

    请注意:

    • EXPOSEDockerfiles有关(文件化)
    • --publishdocker run ...有关(执行/运行时)

    Exposing and publishing ports

    In Docker networking, there are two different mechanisms that directly involve network ports: exposing and publishing ports. This applies to the default bridge network and user-defined bridge networks.

    • You expose ports using the EXPOSE keyword in the Dockerfile or the --expose flag to docker run. Exposing ports is a way of documenting which ports are used, but does not actually map or open any ports. Exposing ports is optional.

    • You publish ports using the --publish or --publish-all flag to docker run. This tells Docker which ports to open on the container’s network interface. When a port is published, it is mapped to an available high-order port (higher than 30000) on the host machine, unless you specify the port to map to on the host machine at runtime. You cannot specify the port to map to on the host machine when you build the image (in the Dockerfile), because there is no way to guarantee that the port will be available on the host machine where you run the image.

    from: Docker container networking

    也,

    EXPOSE

    ...The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.

    from: Dockerfile reference

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

    在@golo roden的回答中,声明:

    "If you do not specify any of those, the service in the container will not be accessible from anywhere except from inside the container itself."

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

    如何测试:

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

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

    i build图像为"testexpose",run是一个新的容器,具有:

    1
    docker run --rm -it testexpose bash

    在容器内,我启动了几个mini-httpd的实例:

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

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


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

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

    您可以在docker run中使用-p来控制暴露的集装箱端口可连接的公共端口。

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

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


    使用dockerfile中的expose关键字或--向Docker运行公开标志。公开端口是一种记录端口被使用,但实际上并不映射或打开任何端口。暴露端口是可选的。

    来源:Github提交


    大多数人使用Docker与网络组合。文件规定:

    The Docker network feature supports creating networks without the need to expose ports within the network, for detailed information see the overview of this feature).

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


    Dockerfile公开vs发布

    暴露

    在编写dockerfiles时,expose指令告诉docker正在运行的容器监听特定的网络端口。这是一种端口映射文档,可以在发布端口时使用。

    暴露[…]

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

    docker run--expose=1234我的应用程序

    但expose不允许通过定义的端口与同一网络之外的容器或主机进行通信。要允许这种情况发生,您需要发布端口。

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

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

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

    docker run-p 80:80/tcp-p 80:80/udp my_应用程序

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

    要使用expose发布Dockerfile中定义的所有端口并将它们绑定到主机,可以使用-p标志。

    docker run-p my_应用程序