Docker部署服务,避免PID=1

Docker部署java服务时,通常写为 CMD ["java", "-jar", "app.jar"],这样会导致java进程的PID=1,这样会带来一些问题,例如无法使用arthas工具分析JVM,jstack,jmap等命令的使用也会存在问题。

此时可以使用 tini 工具,tini是一个小型的守护进程初始化系统,主要用于容器环境下作为 PID 为 1 的 init 进程。在 Linux 系统中,PID(进程标识符)为 1 的进程具有特殊的意义,它是系统的第一个进程,也称为 init 进程,负责创建、管理和终止其他所有进程,并且能够正确地处理和转发信号给其子进程。

在 Docker 容器中,由于容器通常会直接运行用户指定的应用程序而非一个完整的 init 系统(如 Systemd 或 Upstart),因此有时候会出现信号处理不当或者僵尸进程的问题。具体问题包括:

  • 僵尸进程(Zombie Process):当子进程终止但父进程没有正确地调用 wait() 函数回收其资源时,子进程就会变为僵尸进程。在容器环境中,若父进程未能妥善处理这种情况,可能会导致僵尸进程堆积。

  • 信号转发(Signal Propagation):当发送给容器的信号(例如通过 docker stop 发送的 SIGTERM)被容器内的 PID 1 进程接收到时,需要确保这些信号能够正确地传递给所有的子进程。标准 shell(如 bash 或 sh)并不总是适合作为容器的 PID 1 进程,因为它们可能无法正确处理或转发信号。

tini 的作用在于:

  • 防止僵尸进程:tini 作为 PID 1 的 init 进程,会持续监控并正确地回收其子进程,>从而避免僵尸进程的产生。

  • 信号转发:tini 将接收到的任何信号透明地转发给所有子进程,确保容器内的应用程序能够及时响应操作系统发出的信号,从而允许容器能够优雅地停止、重启等。

# 使用tini

容器中需要安装tini,可以在Dockerfile中添加如下命令:

RUN apk add --no-cache tini
1

然后在启动容器时,使用 tini 命令启动应用程序:

CMD ["/sbin/tini", "--", "java", "-jar", "app.jar"]
#或者使用ENTRYPOINT
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["java", "-jar", "app.jar"]
1
2
3
4
上次更新: 2024/11/27, 13:48:55
最近更新
01
docker-compose笔记
01-12
02
MySQL数据迁移
11-27
03
Skywalking笔记
11-21
更多文章>