我正在尝试使用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默认页面
参考官方文档: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可以很有用。
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指令公开在链接中使用的端口。
它还指出了如何链接容器,这基本上就是我所说的容器间通信。