知微坚果的拾光小镇 知微坚果的拾光小镇
首页
随笔
  • Golang

    • 基础
    • 第三方库
  • 前端

    • Vue
    • Flutter
  • 开发工具
  • 系统工具
  • Timer (opens new window)
  • 时间线
  • 关于
GitHub (opens new window)

知微坚果

行者常至,为者常成
首页
随笔
  • Golang

    • 基础
    • 第三方库
  • 前端

    • Vue
    • Flutter
  • 开发工具
  • 系统工具
  • Timer (opens new window)
  • 时间线
  • 关于
GitHub (opens new window)
  • 运维
知微坚果
2022-11-29
目录

解决Docker启动java进程号1的问题

# 前言

我们在Java容器中,经常需要用到jmap等命令,但是默认Java启动的进程号是1,无法使用这些命令。

# 解决spring boot应用以docker容器方式启动后,进程ID是1而导致的jstack和jmap等命令不可用的现象

默认将spring boot工程打包成镜像的方式

  1. 当我们把spring boot打包成一个可执行jar
  2. 编写Dockerfile 将jarcopy到容器中,在cmd 中执行java -jar ***.jar 启动,Dockerfile文件如下
#基础镜像基于openjdk,利用alpine  
FROM openjdk:8u212-jdk-alpine  
#所属团队  
MAINTAINER chengf  
  
ENV JAVA_OPTS="-server -Xms512m -Xmx512m" LOGGING_LEVEL="INFO"  
#编译时变量无法在运行时用,此处做一次转换  
ENV TARGET_JAR="spring-boot-sample-0.0.1-SNAPSHOT.jar"  
  
#将编译好的工程jar包copy到镜像容器中  
COPY ${TARGET_JAR} /usr/src/${TARGET_JAR}  
  
  
ENV OPTS=${JAVA_OPTS}" -Dfile.encoding=UTF8    -Duser.timezone=GMT+08"  
WORKDIR /usr/src  
#程序入口  
  
  
CMD java -jar ${OPTS} ${TARGET_JAR} --logging.level.root=${LOGGING_LEVEL}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

启动镜像后执行docker exec 进入到容器内部,执行ps可以看到容器中进程号是1的就是我们的应用启动进程

# 解决办法

解决办法 因为jstack jmap等jdk自带的tools放发无法对1号进程分析,那我们就想办法把java进程变为非1号进程对应的Dockerfile

#基础镜像基于openjdk,利用alpine  
FROM openjdk:8u212-jdk-alpine  

ENV JAVA_OPTS="-server -Xms512m -Xmx512m" LOGGING_LEVEL="INFO"  
#编译时变量无法在运行时用,此处做一次转换
ENV TARGET_JAR="spring-boot-sample-0.0.1-SNAPSHOT.jar"

#将编译好的工程jar包copy到镜像容器中  
COPY ${TARGET_JAR} /usr/src/${TARGET_JAR}  

ENV OPTS=${JAVA_OPTS}" -Dfile.encoding=UTF8    -Duser.timezone=GMT+08"
WORKDIR /usr/src  
#程序入口  

#CMD java -jar ${OPTS} ${TARGET_JAR} --logging.level.root=${LOGGING_LEVEL}  

RUN echo "java -jar \${OPTS} \${TARGET_JAR} --logging.level.root=\${LOGGING_LEVEL}" > start.sh \
             && chmod 777 start.sh
# CMD ./start.sh
ENTRYPOINT ["./start.sh"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

这样启动后1号进程就变成了 start.sh 由1号进程启动的进程才是我们的java进程

# 总结

不管通过什么方式 只要让启动命令不是第一个执行的就能解决问题。

# 相关问题

https://github.com/alibaba/arthas/issues/362 https://github.com/docker-library/openjdk/issues/76 https://github.com/krallin/tini

# 参考资料

解决spring boot应用以docker容器方式启动后,进程ID是1而导致的jstack和jmap等命令不可用的问题 https://www.iteye.com/blog/fengyilin-2451011

更新时间: 12/4/2022, 6:55:46 PM
最近更新
01
SpringBoot3.0快速上手
12-07
02
Spring事务管理源码分析
12-06
03
Golang工程结构最佳实践
12-04
更多文章>
Theme by Vdoing | Copyright © 2022-2022 知微坚果 | 拾光小镇
蜀ICP备17001150号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式