Extracting Java dump is usually straightforward task, until I tried to get the thread dump from the Java process with PID 1 in the alpine based docker container, based on docker image openjdk:8-jre-alpine. Everyone love alpine variant because it’s so small in size, light and secure!
From the snippet below you can see that the Java process is running with PID 1, which is the root process. I then attempt to get a thread dump with jstack, oopssss…
$ docker exec -ti 202 sh /opt/app $ ps PID USER TIME COMMAND 1 root 9:54 java -server -Xms2g -Xmx4g ... 203 root 0:00 ps /opt/app $ jstack 1 Unable to get pid of LinuxThreads manager thread
kill -3 doesn’t work either! After some poking at Google, I learnt that this was because PID 1 is special and it doesn’t handle any signal unless explicitly declared. So the workaround is to have the java process spawned at non PID 1. Here comes Tini into play!
All Tini does is spawn a single child (Tini is meant to be run in a container), and wait for it to exit. All the while reaping zombies and performing signal forwarding.
In the docker file, I made the following changes (git diff).
FROM openjdk:8-jre-alpine ... + # Install Tini + RUN apk add --no-cache tini - ENTRYPOINT ["sh", "entrypoint.sh"] + ENTRYPOINT ["/sbin/tini", "--", "sh", "entrypoint.sh"]
Redeployed the application, and I can finally run some analysis on the JVM with jstack, jmap etc. Now the process will look like this. See that tini is running on PID 1 and it spawn the Java process at PID 6. Sweet!
/opt/app # ps PID USER TIME COMMAND 1 root 0:23 /sbin/tini -- sh entrypoint.sh 6 root 2d00 java -server -Xms2g -Xmx4g ... 984 root 0:00 ps
Love and hate of Alpine pffff…