红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 开发工具
  3. 正文

Docker 容器启动后自动退出

2023年7月28日 986点热度 0人点赞 0条评论

问题描述

创建了一个用于启动 jar 包的 Docker 容器,启动后自动退出:

[icexmoon@192 ~]$ docker run --name jw -d -p 8090:8090 javaweb:1.0
ef2ae3996f2209c30fbb928ed8def438014d8028ea2d24ec55b40bd9a6fef602
[icexmoon@192 ~]$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                   CREATED         STATUS                       PORTS     NAMES
ef2ae3996f22   javaweb:1.0   "/bin/sh -c 'java -j…"   7 seconds ago   Exited (134) 3 seconds ago             jw

查看容器日志显示:

[icexmoon@192 ~]$ docker logs jw
library initialization failed - unable to allocate file descriptor table - out of memoryAborted (core dumped)

问题排查

查看宿主机的系统日志:

[icexmoon@192 ~]$ sudo tail -n 100 /var/log/messages
...
Jul 28 13:11:38 localhost systemd-coredump[3424]: Process 3410 (java) of user 0 dumped core.#012#012Stack trace of thread 8:#012#0  0x00007f624cc99438 n/a (/lib/x86_64-linux-gnu/libc-2.23.so + 0x35438)#012#1  0x00007f623090fc86 n/a (/usr/local/java8/jre/lib/amd64/libnet.so + 0x12c86)#012#2  0x00007f623090133b n/a (/usr/local/java8/jre/lib/amd64/libnet.so + 0x433b)#012ELF object binary architecture: AMD x86-64
...

我这里的宿主机是 RockyLinux 9,RHEL 系列的日志文件都类似。但其他的发行版日志文件可能会有所不同。

只能说明调用函数库时出错,没有更多的错误信息。

问题解决

在往上查找类似问题的时候,发现可能是 ulimit 的限制导致类似问题的发生。

先修改宿主机的 ulimit 限制:

[icexmoon@192 ~]$ sudo vim /etc/security/limits.conf

添加以下内容:

* soft noproc 65535
* hard noproc 65535
* soft nofile 65535
* hard nofile 65535
* soft core   unlimited

这里* soft noproc 65535的意思是修改所有用户的进程数上限为65535。

关于 ulimit 的更多介绍可以阅读ulimit 命令详解。

查看修改结果:

[icexmoon@192 ~]$ ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
...
open files                          (-n) 65535
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 30402
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

比较重要就是open files,即上面修改的nofile配置项,这里已经变为65535。

如果没有改变,重启宿主机。

光宿主机修改还不够,还需要修改容器的这个选项,这点可以在启动容器时通过参数指定:

docker run --name jw --entrypoint bash -p 8090:8090 --ulimit nofile=65535:65535 --ulimit nproc=65535:65535 -it javaweb:1.0
  • 为了方便起见,这里先用 bash 作为容器的启动入口启动容器,以防止容器直接启动失败。这样可以方便进行调试。

  • 因为要进入容器进行调试,所以这里没有加-d参数以后台服务方式启动容器。

  • 不要忘记加-it参数,否则不能将宿主机的标准输入输出(屏幕和键盘)接入容器。

进入容器的 Bash 环境后,查看容器的 ulimit 限制:

root@9e1365a86947:/# ulimit -a
...
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 65535
...

很明显,这里的最大文件打开数(open files)和最大用户进程数(max user processes)已经修改为65535。

要验证我们的修改有没有用,可以在容器中直接启动 jar 包:

root@9e1365a86947:/# java -jar /tmp/app.jar

能看到 Spring Boot 的欢迎信息说明程序已经可以正常启动。

现在其实已经解决了问题,每次启动运行 jar 包的镜像时加上相关参数即可,比如:

[icexmoon@192 ~]$ docker run --name jw -p 8090:8090 -d --ulimit nofile=65535:65535 --ulimit nproc=65535:65535 javaweb:1.0

但这样会显得很麻烦,我们可以修改默认的 Docker 镜像启动参数:

[icexmoon@192 ~]$ locate docker.service
/etc/systemd/system/multi-user.target.wants/docker.service
/usr/lib/systemd/system/docker.service
[icexmoon@192 ~]$ cd /usr/lib/systemd/system/
[icexmoon@192 system]$ sudo vim docker.service

内容修改如下:

[Service]
# ...
ExecStart=/usr/bin/dockerd --default-ulimit nofile=65535:65535 -H fd:// --containerd=/run/containerd/containerd.sock
# ...

在ExecStart中添加参数--default-ulimit nofile=65535:65535。

重新加载并启动 Docker 服务:

[icexmoon@192 system]$ sudo systemctl daemon-reload
[icexmoon@192 system]$ sudo systemctl restart docker

现在可以不带 ulimit 相关参数启动容器了:

[icexmoon@192 system]$ docker run --name jw -p 8090:8090 -d javaweb:1.0

The End,谢谢阅读。

参考资料

  • ulimit 命令详解 - zengkefu - 博客园 (cnblogs.com)

  • library initialization failed - unable to allocate file descriptor table - out of memoryAborte

  • Java -jar参数详解:掌握Java可执行JAR文件的运行技巧 - 知乎 (zhihu.com)

  • docker容器直接退出,如何进入容器调试 - 钟灵.毓秀 - 博客园 (cnblogs.com)

  • Docker无法正常启动的原因及解决办法 - 简书 (jianshu.com)

  • docker-compose 启动 java 容器时报错 library initialization failed - unable to allocate file descriptor table - iyiluo - 博客园 (cnblogs.com)

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: docker
最后更新:2023年7月28日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇
下一篇 >

文章评论

取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号