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

Unable to access published ports in Docker from local machine

我想对较旧的 jboss 服务器 (7.0.0) 进行 docker 化。这是我的 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。我在这里错过了什么?

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

...Undertow HTTP listener default listening on 127.0.0.1:8080 ...listening on http://127.0.0.1:9990/management ...listening on http://127.0.0.1:9990

Docker文件有两种形式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-array 形式,您可以在 docker run 选项中的图像名称后指定其他选项,或作为 Compose command:。如果您使用 shell 形式,命令部分将被完全忽略。

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