简短回答:
EXPOSE
是一种文档化的方式
--publish
(或 -p
)是一种将主机端口映射到运行中的容器端口的映射方式
请注意以下内容:
EXPOSE
与Dockerfiles
相关(用于文档编写)
--publish
与docker run ...
相关(用于执行/运行时)
暴露和发布端口
在Docker网络中,有两种直接涉及网络端口的机制:暴露和发布端口。这适用于默认桥接网络和用户定义的桥接网络。
您可以使用Dockerfile中的EXPOSE
关键字或--expose
标志来暴露端口。暴露端口是一种记录使用哪些端口的方式,但不会映射或打开任何端口。暴露端口是可选的。
您可以使用--publish
或--publish-all
标志来docker run
发布端口。这告诉Docker在容器的网络接口上打开哪些端口。当端口被发布时,它将映射到主机机器上的一个可用高阶端口(高于30000
),除非您在运行时指定要映射到主机机器上的端口。您不能在构建镜像时(在Dockerfile中)指定要映射到主机机器上的端口,因为没有办法保证在运行图像的主机机器上该端口可用。
来源:Docker container networking
更新于2019年10月:上述文本已不再出现在文档中,但存档版本在此处:docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports
也许当前的文档如下:
发布端口
默认情况下,创建容器时,它不会将任何端口发布到外部服务或未连接到容器网络的Docker容器。要使端口对Docker之外的服务或未连接到容器网络的Docker容器可用,请使用--publish
或-p
标志。这将创建一个防火墙规则,将容器端口映射到Docker主机上的端口。
可在此处找到:docs.docker.com/config/containers/container-networking/#published-ports
另外,
EXPOSE
EXPOSE
指令不会实际发布端口。它作为一种文档的形式,在构建镜像的人和运行容器的人之间记录哪些端口应该被发布。
来自:Dockerfile 参考手册
在未定义EXPOSE
/ --publish
时访问服务:
在@Golo Roden's的答案中,有如下陈述:
"如果你没有指定任何一个选项,容器内的服务只能从容器内部访问。"
也许在回答写作时是这种情况,但现在似乎即使您不使用EXPOSE
或--publish
,同一网络的host
和其他containers
也能够访问您在该容器内启动的服务。
如何测试:
我使用了以下Dockerfile
。基本上,我从Ubuntu开始并安装了一个小型Web服务器:
FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
我使用"testexpose"构建镜像,并使用以下命令运行新容器:
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
的主页。
更多阅读
Ivan Pepelnjak撰写的关于该主题的非常详细的文章:
EXPOSE
和-p
,而不是前面的三个项目符号所列举的内容。这样会更容易理解。 - Pithikos