介绍
- 我正在开发一个专有应用程序,它使用
libevent
withlibevhtp
来创建用于 http 通信的服务器套接字。 - 我编写了一个
Dockerfile
将此应用程序放置在 docker 映像中的程序。
生成的 docker 映像默认启动应用程序,通过运行该映像在我测试过的其他计算机(ubuntu 20.04/22.04)上运行良好
docker run --rm -p 8080:8080 -t mytag
- 我可以从同一网络内正常连接到该计算机的端口 8080。
- 我可以
docker exec -ti runningcontainer bash
查看正在运行的容器并netstat -pntl
查看应用程序正在侦听端口 8080。
问题
在我的笔记本电脑上,情况并非如此。我没有像我尝试过的其他服务器那样运行 Ubuntu。我在 Manjaro 上。但我不明白这有什么关系。
- 在我的笔记本电脑上正在运行的 docker 容器内以及正在运行的应用程序中,
netstat -pntl
显示没有侦听套接字 - 因此我无法连接到应用程序的端口 8080 -
curl localhost:8080
返回Connection Refused
- 在我的计算机上本机(而不是在 docker 中)运行应用程序按预期工作,我可以访问端口 8080
nc -l 0.0.0.0 9999
在我的笔记本电脑上运行的 docker 容器中运行会打开一个套接字并netstat
报告它正在侦听。nc 127.0.0.1 9999
从容器内部到打开的套接字的连接按预期工作。- 我尝试运行容器,
--privileged
结果相同 - 不起作用 - 我已经修剪了所有 docker 镜像、容器、网络,从我的计算机中卸载并删除了 docker 的所有痕迹,然后重新安装了它,行为没有任何变化
结论
在我看来,由于某种原因,应用程序在 docker 容器内运行时没有打开任何侦听套接字。实现的日志没有显示错误 - 注意:我还没有检查实现是否有错误或一些被忽略的错误代码。
我需要帮助弄清楚如何尝试以最有效的方式进行调试。
我的下一步是
- 使用 libevhtp 创建一个小的二进制文件来提供 test.html 文件,并尝试在 docker 中运行它 - 如果运行正常
- 慢慢地一点一点地禁用出现故障的应用程序的某些部分,直到找到罪魁祸首。
第二步将需要大量工作,因此我会在这里联系,以防有人遇到类似问题,或者可以指出我在进行这项工作之前可以尝试的一些事情。
答案1
发现
在启用不同模块的情况下,初始化总是失败,这会耗尽可用的文件描述符。当套接字被绑定时,已经没有了。当我尝试lsof
在 docker 中使用时,我陷入了困境,并早些时候放弃了,因为有太多的可能性导致它无法工作。 (看如何在 Docker 中替换 lsof(本机,不是基于 LXC))
最后谷歌搜索有关文件描述符限制:
# uname -r
5.15.106-1-MANJARO
# ulimit -n
1024
以及一个有用的答案:https://stackoverflow.com/questions/24318543/为我解决了这个问题。
解决方案:
--ulimit
带参数运行 docker
docker run --rm -p 8080:8080 --ulimit nofile=262144:262144 -ti mytag:latest bash
更新:
根据这个线程:https://github.com/moby/moby/issues/44547
一个半永久性的解决方案似乎是将文件中的LimitNOFILE
值从更改infinity
为。系统升级后,您可能需要重复此操作。 此线程中概述了另一种解决方案:1048576
/usr/lib/systemd/system/containerd.service
https://bbs.archlinux.org/viewtopic.php?id=285058建议创建一个 docker 设置文件来/etc/docker/daemon.json
设置 docker 的默认 ulimit,如下所示:
{
"default-ulimits": {
"nofile": {
"Hard": 1048576,
"Name": "nofile",
"Soft": 1048576
}
}
}
然后运行systemctl reload docker
以应用更改。