我正在尝试使用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

这可能吗?


当前回答

EXPOSE关键字允许所有者通知其他人容器将主要使用哪些端口。

即使没有在EXPOSE中指定端口,也可以发布任何端口。

例如,我们用nginx镜像创建一个Dockerfile,公开端口1234

FROM nginx:latest
EXPOSE 1234

然后建造它

Docker build -t porttest。

并将80端口发布到localhost:80来运行它

Docker运行-p 80:80 porttest

当你进入localhost:80,你会看到nginx默认页面。 Nginx默认页面

其他回答

可以使用Dockerfile中的expose关键字或 ——将标志暴露给docker运行。公开端口是一种记录端口的方法 使用了端口,但实际上没有映射或打开任何端口。暴露的港口 是可选的。

来源:github提交

参考官方文档:https://docs.docker.com/engine/reference/builder/#expose

如果使用-P运行容器,则EXPOSE允许您定义私有(容器)和公共(主机)端口,以便在映像构建时为容器运行时公开。

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

公共端口和协议是可选的,如果没有指定公共端口,docker将在主机上随机选择一个端口,在Dockerfile上公开指定的容器端口。

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

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

无论如何,如果你不使用EXPOSE(在docker运行时使用-P)或-P,就不会暴露任何端口。

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

大多数人使用docker组合网络。文件说明:

Docker网络特性支持创建网络而不需要暴露网络中的端口,详细信息请参阅此特性的概述)。

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

EXPOSE关键字允许所有者通知其他人容器将主要使用哪些端口。

即使没有在EXPOSE中指定端口,也可以发布任何端口。

例如,我们用nginx镜像创建一个Dockerfile,公开端口1234

FROM nginx:latest
EXPOSE 1234

然后建造它

Docker build -t porttest。

并将80端口发布到localhost:80来运行它

Docker运行-p 80:80 porttest

当你进入localhost:80,你会看到nginx默认页面。 Nginx默认页面

基本上,你有三(四)种选择:

不要指定EXPOSE或-p 只指定EXPOSE 指定EXPOSE和-p 只指定隐式执行EXPOSE的-p

If you specify neither EXPOSE nor -p, the service in the container will only be accessible from inside the container itself. If you EXPOSE a port, the service in the container is not accessible from outside Docker, but from inside other Docker containers. So this is good for inter-container communication. If you EXPOSE and -p a port, the service in the container is accessible from anywhere, even outside Docker. If you do -p, but do not EXPOSE, Docker does an implicit EXPOSE. This is because if a port is open to the public, it is automatically also open to other Docker containers. Hence -p includes EXPOSE. This is effectively same as 3).

以我之见,两者分开的原因是:

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

文档明确指出:

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

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