Docker Compose中Java容器启动失败:VM Thread创建失败(EPERM)
问题描述
尝试通过Docker Compose运行包含Java服务的多容器应用时,Next.js的web容器可正常启动,但两个Java服务初始化失败,报错信息如下:
[0.103s][warning][os,thread] Failed to start thread "VM Thread" - pthread_create failed (EPERM) for attributes: stacksize: 1024k, guardsize: 4k, detached. Error occurred during initialization of VM Cannot create VM thread. Out of system resources.
Docker Compose日志输出:
Attaching to compass-admin_resource_1, compass-admin_api_1, compass-admin_web_1 api_1 | [0.103s][warning][os,thread] Failed to start thread "VM Thread" - pthread_create failed (EPERM) for attributes: stacksize: 1024k, guardsize: 4k, detached. api_1 | Error occurred during initialization of VM api_1 | Cannot create VM thread. Out of system resources. resource_1 | [0.046s][warning][os,thread] Failed to start thread "VM Thread" - pthread_create failed (EPERM) for attributes: stacksize: 1024k, guardsize: 4k, detached. resource_1 | Error occurred during initialization of VM resource_1 | Cannot create VM thread. Out of system resources. web_1 | ▲ Next.js 14.2.16 web_1 | - Local: http://af26e35c0d2b:3000 web_1 | - Network: http://192.168.128.4:3000 web_1 | web_1 | ✓ Starting... web_1 | ✓ Ready in 73ms
已验证主机内存和CPU资源充足、运行命令权限足够,需排查该问题的成因及解决方法。
成因分析
- Docker容器线程数限制:即使主机资源充足,Docker默认可能给容器设置了过低的线程数阈值,JVM启动时需要创建多个核心线程(如VM Thread、GC线程等),超过容器允许的线程上限就会触发
EPERM错误。 - 主机系统线程配额不足:主机的
ulimit配置(如nproc参数)限制了当前用户可创建的线程总数,若主机已运行大量进程,分配给Docker容器的线程配额会被耗尽。 - Java镜像权限缺失:部分Java基础镜像使用非root用户运行,该用户在容器内没有足够权限创建线程,或容器未配置必要的系统能力(capabilities)。
解决方法
1. 在Docker Compose中配置容器线程限制
在docker-compose.yml的Java服务节点下添加ulimits字段,调高线程数和文件句柄限制:
services: api: image: your-java-api-image ulimits: nproc: 65535 nofile: soft: 65535 hard: 65535 resource: image: your-java-resource-image ulimits: nproc: 65535 nofile: soft: 65535 hard: 65535
2. 调整主机的ulimit配置
临时生效(重启后失效)
执行命令调高当前用户的线程数上限:
ulimit -u 65535
永久生效
编辑/etc/security/limits.conf,添加以下配置:
* soft nproc 65535 * hard nproc 65535
保存后重启Docker服务:
systemctl restart docker
3. 配置Java容器的运行权限
方式A:添加系统能力(capabilities)
在docker-compose.yml中给Java服务添加线程相关的系统权限:
services: api: image: your-java-api-image cap_add: - SYS_NICE - SYS_RESOURCE
方式B:以root用户运行(注意安全风险)
若对容器安全性要求不高,可直接指定root用户启动Java服务:
services: api: image: your-java-api-image user: root
4. 调整JVM线程参数
启动Java服务时,通过JVM参数减少线程创建数量,比如限制GC线程数:
java -XX:ParallelGCThreads=2 -XX:ConcGCThreads=1 -jar your-app.jar
可将此命令写入Dockerfile的CMD/ENTRYPOINT,或在docker-compose.yml的command字段中配置。
内容的提问来源于stack exchange,提问作者이수민
相关产品推荐
相关产品推荐

