【发布时间】:2020-02-03 00:37:09
【问题描述】:
docker-compose.yml 中的ports 和expose 选项有什么区别?
【问题讨论】:
标签: docker docker-compose
docker-compose.yml 中的ports 和expose 选项有什么区别?
【问题讨论】:
标签: docker docker-compose
公开端口。要么指定两个端口 (HOST:CONTAINER),要么只指定容器端口(将选择随机主机端口)。
我的docker-compose.yml 看起来像:
mysql:
image: mysql:5.7
ports:
- "3306"
如果我做docker-compose ps,它看起来像:
Name Command State Ports
-------------------------------------------------------------------------------------
mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:32769->3306/tcp
公开端口而不将它们发布到主机 - 它们只能被链接的服务访问。只能指定内部端口。
端口不暴露给主机,只暴露给其他服务。
mysql:
image: mysql:5.7
expose:
- "3306"
如果我做docker-compose ps,它看起来像:
Name Command State Ports
---------------------------------------------------------------
mysql_1 docker-entrypoint.sh mysqld Up 3306/tcp
在最新版本的 Dockerfile 中,EXPOSE 不再对操作产生任何影响,它只是提供信息。 (see also)
【讨论】:
docker-compose 中指定expose 有什么优势?据我所知,您不需要指定公开来使链接服务可以访问端口。
expose:“EXPOSE 指令实际上并没有发布端口。它的功能是一种文档...”docs.docker.com/engine/reference/builder/#expose
docker-compose run,docker-compose.yml 中的端口定义默认忽略。使用docker-compose up 或提供参数--service-ports
【讨论】:
端口 该部分用于定义主机服务器和 Docker 容器之间的映射。
ports:
- 10005:80
表示容器内运行的应用暴露在80端口,但外部系统/实体无法访问,需要映射到宿主服务器端口。
注意:您必须打开主机端口 10005 并修改防火墙规则以允许外部实体访问应用程序。
他们可以使用
http://{主机 IP}:10005
类似的东西
曝光 这专门用于定义在 docker 容器内运行应用程序的端口。
您也可以在 dockerfile 中定义它。一般来说,在 dockerfile 中定义 EXPOSE 是一种很好且广泛使用的做法,因为很少有人在默认 80 端口以外的其他端口上运行它们
【讨论】:
ports 部分将在主机上发布端口。 Docker 将为从主机网络到容器的特定端口设置转发。默认情况下,这是通过用户空间代理进程 (docker-proxy) 实现的,该进程侦听第一个端口,然后转发到需要侦听第二个端口的容器。如果容器没有在目标端口上侦听,您仍然会在主机上看到一些东西正在侦听,但是如果您尝试连接到该主机端口,则会从失败的转发到您的容器中获得连接被拒绝。
请注意,容器必须监听所有网络接口,因为此代理不在容器的网络命名空间内运行,并且无法到达容器内的 127.0.0.1。 IPv4 方法是将您的应用程序配置为侦听0.0.0.0。
另请注意,已发布的端口不会以相反的方向工作。您无法通过发布端口从容器连接到主机上的服务。相反,您会发现尝试侦听已在使用的主机端口时出现 docker 错误。
公开是文档。它在图像上设置元数据,并且在运行时也在容器上设置元数据。通常,您在 Dockerfile 中使用 EXPOSE 指令进行配置,它作为运行您的镜像的用户的文档,让他们知道默认情况下您的应用程序将侦听哪些端口。当使用 compose 文件配置时,此元数据仅在容器上设置。当您在映像或容器上运行 docker inspect 时,您可以看到暴露的端口。
有一些工具依赖于暴露的端口。在 docker 中,-P 标志会将所有暴露的端口发布到主机上的临时端口上。如果您没有明确设置容器端口,那么在向您的应用程序发送流量时,还有各种反向代理默认使用公开端口。
除了那些外部工具之外,expose 对容器之间的网络完全没有影响。您只需要一个通用的 docker 网络,并连接到容器端口,就可以从另一个容器访问一个容器。如果该网络是用户创建的(例如,不是名为 bridge 的默认桥接网络),您可以使用 DNS 连接到其他容器。
【讨论】:
我完全同意之前的答案。 我只想提一下,expose 和 ports 之间的区别是 docker 中安全概念的一部分。它与 docker 的 networking 齐头并进。 例如:
想象一个具有 Web 前端和数据库后端的应用程序。 外部世界需要访问 web 前端(可能在端口上) 80),但只有后端本身需要访问数据库主机 和港口。使用用户定义的网桥,只需要 web 端口 打开,并且数据库应用程序不需要打开任何端口, 因为网络前端可以通过用户定义的网桥访问它。
这是在 docker 中设置网络架构时的常见用例。 因此,例如在默认桥接网络中,外部世界无法访问端口。 因此,您可以使用“端口”打开一个入口点。通过使用“公开”,您可以定义网络内的通信。如果要公开默认端口,则无需在 docker-compose 文件中定义“公开”。
【讨论】: