无法从本地机器访问 Docker 中已发布的端口

Posted

技术标签:

【中文标题】无法从本地机器访问 Docker 中已发布的端口【英文标题】:Unable to access published ports in Docker from local machine 【发布时间】:2021-12-10 23:16:36 【问题描述】:

我想对旧的 jboss 服务器 (7.0.0) 进行 dockerize。这是我的Dockerfiledocker-compose.yml

FROM centos:7.9.2009

RUN yum -y install java-1.8.0-openjdk-devel unzip

COPY jboss-eap-7.0.0.zip .

RUN unzip jboss-eap-7.0.0.zip -d /opt/
RUN ln -s /opt/jboss-eap-7.0/ /opt/jboss
RUN adduser jboss
RUN chown -R jboss /opt/jboss-eap-7.0/ /opt/jboss

ENTRYPOINT [ "/opt/jboss/bin/standalone.sh -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0" ]
version: '3.0'

services:
  ab3:
    build: .
    ports:
      - "8080:8080"
      - "9990:9990"

在日志中我可以看到 jboss 已经成功启动并且正在监听端口:

INFO  [org.wildfly.extension.undertow] (MSC service thread 1-5) WFLYUT0006: Undertow HTTP listener default listening on 127.0.0.1:8080
...
INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990

使用http://localhost:8080/ 在浏览器中签入时,我得到ERR_EMPTY_RESPONSE。我在这里错过了什么?

【问题讨论】:

可能你的一些环回 ip 被防火墙阻止了 我不希望容器以 ENTRYPOINT 行启动;它只运行一个 shell 字,空格和-D 选项被解析为它期望运行的文件名的一部分。考虑删除 JSON 格式 ["..."] 并在那里使用纯 shell 命令。 (我个人也会将ENTRYPOINT 更改为CMD,这样更容易在图像上启动调试shell。) @DavidMaze 使用 CMD 并删除 JSON 格式修复它。如果您将评论更改为答案,我很乐意接受它作为正确答案。 【参考方案1】:

您需要检查为什么您的应用没有绑定到 0.0.0.0,它只会在绑定到 127.0.0.1 时接受容器内的连接:

...Undertow HTTP 监听器默认监听 127.0.0.1:8080 ...收听 http://127.0.0.1:9990/management ...收听 http://127.0.0.1:9990

【讨论】:

【参考方案2】:

Dockerfile 有两种形式的ENTRYPOINTCMD 指令(还有RUN)。如果你指定一个JSON数组,你必须自己把它拆分成单词;数组中的每一项本质上都作为带引号的 shell 词处理。指定一个没有 JSON 语法的裸命令可能更容易,在这种情况下,Docker 会启动一个 shell 来为您处理命令行。

由于您在问题中的表单有一个 JSON 单词,Docker 将尝试将整个单词解释为要运行的命令,包括空格和连字符作为文件名的一部分,并且没有选项。我希望容器根本不会启动,给出“没有这样的文件或目录”错误。您需要手动将命令分解为单独的单词或使用 shell 形式:

# Shell form
ENTRYPOINT /opt/jboss/bin/standalone.sh -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0
# JSON-array form
ENTRYPOINT ["/opt/jboss/bin/standalone.sh", "-Djboss.bind.address=0.0.0.0", "-Djboss.bind.address.management=0.0.0.0"]

如果您使用 JSON 数组形式,您可以在 docker run 选项中的图像名称之后指定其他选项,或者作为 Compose command:。如果您使用 shell 形式,命令部分将被完全忽略。

(对于是否将其设为容器ENTRYPOINTCMD,有一个样式选择。我倾向于使用CMD,因为它更容易执行诸如在图像上启动调试shell 之类的操作,并且因为有是使用ENTRYPOINT 作为包装器进行一些首次设置然后运行CMD 的常见模式。我建议在评论中更改为CMD,但这不是这个答案的必要条件。)

【讨论】:

以上是关于无法从本地机器访问 Docker 中已发布的端口的主要内容,如果未能解决你的问题,请参考以下文章

无法从我的本地主机访问 docker 上的 apache

Docker 容器无法使用特定端口访问本地主机

记一次docker springboot无法访问

无法从同一主机上的Web应用程序泊坞窗访问docker托管的SQL Server

一台物理机器部署多个docker

linux下docker启动nginx无法访问80端口