ChatGPT解决这个技术问题 Extra ChatGPT

docker-compose 端口与暴露之间有什么区别

docker-compose.yml 中的 portsexpose 选项有什么区别?


o
ospider

根据docker-compose reference

端口定义为:

暴露端口。要么指定两个端口 (HOST:CONTAINER),要么只指定容器端口(将选择随机主机端口)。

docker-compose.yml 中提到的端口将在 docker-compose 启动的不同服务之间共享。

端口将暴露给主机的随机端口或给定端口。

我的 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 有什么优势?据我所知,您不需要指定公开来使链接服务可以访问端口。
它不应该告诉暴露的端口只能用于同一个 docker 网络中的服务(大多数部分的链接正在被替换)吗?
@Juicy 我猜它类似于 Dockerfiles 中的 expose:“EXPOSE 指令实际上并没有发布端口。它充当一种文档类型......”docs.docker.com/engine/reference/builder/#expose
端口是否覆盖防火墙级别的任何设置?我只是注意到我没有在防火墙上为 mysql 开放端口,但是可以远程访问它们。我将端口设置为“3306:3306”而不是暴露。
请记住,如果您使用 docker-compose run,则 docker-compose.yml 中的端口定义默认会忽略。使用 docker-compose up 或提供参数 --service-ports
s
steampowered

端口:

激活容器以侦听来自 docker 外部世界的指定端口(可以是相同的主机或不同的机器)以及 docker 内部的可访问世界。可以指定多个端口(这就是端口不是端口的原因)

https://i.stack.imgur.com/Nb6Om.png

暴露:

激活容器以仅从 docker 内部的世界和 docker 外部不可访问的世界侦听特定端口。可以指定多个端口

https://i.stack.imgur.com/s4k6E.png


请注意,expose 允许多个端口 - docs.docker.com/compose/compose-file/#expose - 但是您只提供内部端口而不是内部 + 外部
这是非常重要的部分:“激活容器以仅从内部世界监听特定端口”
s
sorabzone

Ports 此部分用于定义主机服务器和 Docker 容器之间的映射。

ports:
   - 10005:80

这意味着在容器内运行的应用程序暴露在 80 端口。但外部系统/实体无法访问它,因此需要将其映射到主机服务器端口。

注意:您必须打开主机端口 10005 并修改防火墙规则以允许外部实体访问应用程序。

他们可以使用

http://{主机 IP}:10005

像这样的东西

EXPOSE 这专门用于定义在 docker 容器内运行应用程序的端口。

您也可以在 dockerfile 中定义它。通常,在 dockerfile 中定义 EXPOSE 是一种很好且广泛使用的做法,因为很少有人在默认 80 端口以外的其他端口上运行它们


B
BMitch

端口

ports 部分将发布主机上的端口。 Docker 将为从主机网络到容器的特定端口设置转发。默认情况下,这是通过用户空间代理进程 (docker-proxy) 实现的,该进程侦听第一个端口,然后转发到需要侦听第二个端口的容器。如果容器没有在目标端口上侦听,您仍然会在主机上看到某些东西正在侦听,但是如果您尝试连接到该主机端口,则连接被拒绝,从失败的转发到您的容器。

请注意,容器必须监听所有网络接口,因为此代理不在容器的网络命名空间内运行,并且无法到达容器内的 127.0.0.1。 IPv4 方法是将您的应用程序配置为侦听 0.0.0.0

另请注意,已发布的端口不会以相反的方向工作。您无法通过发布端口从容器连接到主机上的服务。相反,您会发现尝试侦听已在使用的主机端口时出现 docker 错误。

暴露

公开是文档。它在图像上设置元数据,并且在运行时也在容器上设置元数据。通常,您可以使用 EXPOSE 指令在 Dockerfile 中进行配置,并将其用作运行映像的用户的文档,让他们知道默认情况下您的应用程序将侦听哪些端口。当使用 compose 文件配置时,此元数据仅在容器上设置。在映像或容器上运行 docker inspect 时,您可以看到暴露的端口。

有一些工具依赖于暴露的端口。在 docker 中,-P 标志会将所有暴露的端口发布到主机上的临时端口上。如果您没有明确设置容器端口,那么在向您的应用程序发送流量时,还有各种反向代理默认使用公开端口。

除了那些外部工具之外,expose 对容器之间的网络完全没有影响。您只需要一个通用的 docker 网络,并连接到容器端口,即可从另一个容器访问一个容器。如果该网络是用户创建的(例如,不是名为 bridge 的默认桥接网络),您可以使用 DNS 连接到其他容器。


听着,伙计们!这个答案可能看起来不太好,但信息量很大。
F
FishingIsLife

我完全同意之前的答案。我只想提一下,expose 和 ports 之间的区别是 docker 中安全概念的一部分。它与 docker 的 networking 齐头并进。例如:

想象一个具有 Web 前端和数据库后端的应用程序。外界需要访问 Web 前端(可能在 80 端口),但只有后端本身需要访问数据库主机和端口。使用用户定义的网桥,只需要打开 Web 端口,而数据库应用程序不需要打开任何端口,因为 Web 前端可以通过用户定义的网桥访问它。

这是在 docker 中设置网络架构时的常见用例。因此,例如在默认桥接网络中,外部世界无法访问端口。因此,您可以使用“端口”打开一个入口点。通过使用“公开”,您可以定义网络内的通信。如果要公开默认端口,则无需在 docker-compose 文件中定义“公开”。