本文翻译自:What is the difference between “expose” and “publish” in Docker?
I'm experimenting with Dockerfiles, and I think I understand most of the logic. 我正在试验Dockerfile,我想我了解大多数逻辑。 However, I don't see the difference between "exposing" and "publishing" a port in this context. 但是,在这种情况下,我看不到“公开”和“发布”端口之间的区别。
All the tutorials I have seen first include the EXPOSE
command in the Dockerfile: 我首先看过的所有教程都在EXPOSE
中包含EXPOSE
命令:
...
EXPOSE 8080
...
They then build an image from this Dockerfile: 然后,他们从此Dockerfile构建映像:
$ docker build -t an_image - < Dockerfile
And then publish the same port as above when running the image: 然后在运行映像时发布与上述相同的端口:
$ docker run -d -p 8080 an_image
or publish all ports using 或使用以下命令发布所有端口
$ docker run -d -P an_image
What is the point of exposing a port in the Dockerfile, if it will be published anyway? 如果仍要发布端口,则在Dockerfile中公开端口有什么意义? Would there ever be a need to expose a port first, and not publish it later? 是否需要先公开一个端口,然后再不发布它? Effectively, I would like to specify all the ports that I will use in the Dockerfile when creating the image, and then not bother with them again, running them simply with: 实际上,我想指定在创建映像时将在Dockerfile中使用的所有端口,然后不再麻烦它们,只需使用以下命令运行它们:
$ docker run -d an_image
Is this possible? 这可能吗?
#1楼
参考:https://stackoom.com/question/1Um60/Docker中的-公开-和-发布-有什么区别
#2楼
Basically, you have three options: 基本上,您有三个选择:
- Neither specify
EXPOSE
nor-p
既不指定EXPOSE
也不指定-p
- Only specify
EXPOSE
只指定EXPOSE
- Specify
EXPOSE
and-p
指定EXPOSE
和-p
1) If you specify neither EXPOSE
nor -p
, the service in the container will only be accessible from inside the container itself. 1)如果您未指定EXPOSE
或-p
,则只能从容器本身内部访问容器中的服务。
2) If you EXPOSE
a port, the service in the container is not accessible from outside Docker, but from inside other Docker containers. 2)如果EXPOSE
端口,则无法从Docker外部访问容器中的服务,而可以从其他Docker容器内部访问容器中的服务。 So this is good for inter-container communication. 因此,这对于容器间的通信很有用。
3) If you EXPOSE
and -p
a port, the service in the container is accessible from anywhere, even outside Docker. 3)如果使用EXPOSE
并使用-p
端口,则可以从任何地方访问容器中的服务,甚至可以从Docker外部访问。
The reason why both are separated is IMHO because: 两者分开的原因是恕我直言,因为:
- choosing a host port depends on the host and hence does not belong to the Dockerfile (otherwise it would be depending on the host), 选择主机端口取决于主机,因此不属于Dockerfile(否则,将取决于主机),
- and often it's enough if a service in a container is accessible from other containers. 通常,只要可以从其他容器访问某个容器中的服务就足够了。
The documentation explicitly states: 该文档明确指出:
The
EXPOSE
instruction exposes ports for use within links.EXPOSE
指令公开了供链接使用的端口。
It also points you to how to link containers , which basically is the inter-container communication I talked about. 它还为您指出了如何链接容器 ,这基本上就是我所说的容器间通信。
PS: If you do -p
, but do not EXPOSE
, Docker does an implicit EXPOSE
. PS:如果您执行-p
,但不执行EXPOSE
,则Docker会执行隐式EXPOSE
。 This is because if a port is open to the public, it is automatically also open to other Docker containers. 这是因为如果某个端口向公众开放,那么它也会自动向其他Docker容器开放。 Hence -p
includes EXPOSE
. 因此, -p
包括EXPOSE
。 That's why I didn't list it above as a fourth case. 这就是为什么我没有将其列为第四种情况。
#3楼
The EXPOSE
allow you to define private (container) and public (host) ports to expose at image build time for when the container is running. EXPOSE
允许您定义专用(容器)端口和公用(主机)端口,以在映像构建时针对容器运行时公开。 The public port is optional, if not a public port is specified, a random port will be selected on host by docker to expose the specified container port on Dockerfile. 公共端口是可选的,如果未指定公共端口,则docker将在主机上选择一个随机端口以在Dockerfile上公开指定的容器端口。
A good pratice is do not specify public port, because it limits only one container per host ( a second container will throw a port already in use ). 最好不要指定public port,因为每个主机仅限制一个容器(第二个容器将抛出一个已使用的端口)。
You can use -p
in docker run
to control what public port the exposed container ports will be connectable. 您可以在docker run
使用-p
来控制暴露的容器端口可连接的公共端口。
Anyway, If you do not use EXPOSE
nor -p
, no ports will be exposed. 无论如何,如果您既不使用EXPOSE
也不使用-p
,则不会暴露任何端口。
If you always use -p
at docker run
you do not need EXPOSE
but if you use EXPOSE
your docker run
command may be more simple, EXPOSE
can be useful if you don't care what port will be expose on host, or if you are sure of only one container will be loaded. 如果你总是使用-p
在docker run
你不需要EXPOSE
但如果你使用EXPOSE
你的docker run
命令可能更简单, EXPOSE
如果你不关心什么端口将主机被暴露可能是有用的,或者如果你是确保只装载一个容器。
#4楼
Most people use docker compose with networks. 大多数人将docker compose与网络结合使用。 The documentation states: 该文档指出:
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). Docker网络功能支持创建网络,而无需暴露网络中的端口,有关详细信息,请参阅此功能概述。
Which means that if you use networks for communication between containers you don't need to worry about exposing ports. 这意味着,如果您使用网络在容器之间进行通信,则无需担心暴露端口。
#5楼
You expose ports using the EXPOSE keyword in the Dockerfile or the --expose flag to docker run. 您可以在Dockerfile中使用EXPOSE关键字或--expose标志公开端口,以使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. 公开端口是可选的。
Source: github commit 资料来源: github commit
#6楼
Short answer: 简短答案:
-
EXPOSE
is a way of documentingEXPOSE
是文档化的一种方式 -
--publish
(or-p
) is a way of mapping a host port to a running container port--publish
(或-p
)是一种将 主机端口 映射到正在运行的容器端口的方法
Notice below that: 请注意以下几点:
-
EXPOSE
is related toDockerfiles
( documenting )EXPOSE
有关Dockerfiles
( 归档 ) -
--publish
is related todocker run ...
( execution / run-time )--publish
与--publish
docker run ...
( 执行/运行时 )有关
Exposing and publishing ports 公开和发布端口
In Docker networking, there are two different mechanisms that directly involve network ports: exposing and publishing ports. 在Docker网络中,有两种直接涉及网络端口的不同机制:公开端口和发布端口。 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. 您可以在EXPOSE
中使用EXPOSE
关键字或--expose
标志公开端口,以使EXPOSE
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 todocker run
. 您使用--publish
或--publish-all
标志将端口发布到--publish
docker run
。 This tells Docker which ports to open on the container's network interface. 这告诉Docker在容器的网络接口上打开哪些端口。 When a port is published, it is mapped to an available high-order port (higher than30000
) on the host machine, unless you specify the port to map to on the host machine at runtime. 发布端口后,除非您在运行时指定要映射到主机上的端口,否则它将映射到主机上可用的高阶端口(高于30000
)。 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 . 在构建映像时(在Dockerfile中),您无法指定要映射到主机上的端口,因为无法保证端口将在运行映像的主机上可用 。from:
Docker container networking来自:Docker容器网络Update October 2019 : the above piece of text is no longer in the docs but an archived version is here: docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports 2019年10月更新 :以上文本不再包含在文档中,但此处为存档版本: docs.docker.com/v17.09/engine/userguide/networking/#exposed-and-publishing-ports
Maybe the current documentation is the below: 也许当前文档如下:
Published ports 发布的端口
By default, when you create a container, it does not publish any of its ports to the outside world. 默认情况下,创建容器时,它不会将其任何端口发布到外界。 To make a port available to services outside of Docker, or to Docker containers which are not connected to the container's network, use the
--publish
or-p
flag. 要使端口可用于Docker外部的服务或未连接到容器网络的Docker容器,请使用--publish
或-p
标志。 This creates a firewall rule which maps a container port to a port on the Docker host. 这将创建一个防火墙规则,该规则将容器端口映射到Docker主机上的端口。and can be found here: docs.docker.com/config/containers/container-networking/#published-ports 并可以在这里找到: docs.docker.com/config/containers/container-networking/#published-ports
Also, 也,
EXPOSE 暴露
...The
EXPOSE
instruction does not actually publish the port . ...EXPOSE
指令实际上并未发布端口 。 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 来自: Dockerfile参考
Service access when EXPOSE
/ --publish
are not defined: EXPOSE
/ --publish
时的服务访问:
At @Golo Roden's answer it is stated that:: @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." “如果不指定任何内容,则只能从容器本身内部访问任何地方的容器中的服务。”
Maybe that was the case at the time the answer was being written, but now it seems that even if you do not use EXPOSE
or --publish
, the host
and other containers
of the same network will be able to access a service you may start inside that container. 也许在编写答案时就是这种情况,但是现在看来,即使您不使用EXPOSE
或--publish
,同一网络中的host
和其他containers
也将能够访问您可以启动的服务在那个容器里。
How to test this: 如何测试:
I've used the following Dockerfile
. 我使用了以下Dockerfile
。 Basically, I start with ubuntu and install a tiny web-server: 基本上,我从ubuntu开始并安装一个小型Web服务器:
FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
I build
the image as "testexpose" and run
a new container with: 我将映像build
为“ testexpose”,并使用以下命令run
新容器:
docker run --rm -it testexpose bash
Inside the container, I launch a few instances of mini-httpd
: 在容器内,我启动了一些mini-httpd
实例:
root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090
I am then able to use curl
from the host or other containers to fetch the home page of mini-httpd
. 然后,我可以使用主机或其他容器中的curl
来获取mini-httpd
的主页。