无法从本地机器访问 Docker 中已发布的端口
Posted
技术标签:
【中文标题】无法从本地机器访问 Docker 中已发布的端口【英文标题】:Unable to access published ports in Docker from local machine 【发布时间】:2021-12-10 23:16:36 【问题描述】:我想对旧的 jboss 服务器 (7.0.0) 进行 dockerize。这是我的Dockerfile
和docker-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 有两种形式的ENTRYPOINT
和CMD
指令(还有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 形式,命令部分将被完全忽略。
(对于是否将其设为容器ENTRYPOINT
或CMD
,有一个样式选择。我倾向于使用CMD
,因为它更容易执行诸如在图像上启动调试shell 之类的操作,并且因为有是使用ENTRYPOINT
作为包装器进行一些首次设置然后运行CMD
的常见模式。我建议在评论中更改为CMD
,但这不是这个答案的必要条件。)
【讨论】:
以上是关于无法从本地机器访问 Docker 中已发布的端口的主要内容,如果未能解决你的问题,请参考以下文章