Docker容器中的僵尸进程问题及解决方案

403 阅读1分钟

背景

项目使用Playwright进行自动化测试。虽然Playwright官方提供了包含浏览器和环境资源的镜像,但由于其JDK版本为17,高于项目需求,我们决定基于Playwright官方镜像自行封装JDK环境和应用镜像。

问题描述

容器在正常运行一段时间后,通过top命令统计发现存在近千个Chrome的僵尸进程。在复现测试中,每次自动化测试会启动六个Chrome相关进程(具有父子关系),测试流程退出后会产生两个Chrome僵尸进程。这个问题在Playwright的GitHub项目中已有相关讨论。

问题原因

在Docker容器中,默认情况下缺少init进程。在Linux系统中,PID为1的init进程负责:系统初始化、启动系统服务、收养孤儿进程、处理僵尸进程、处理系统信号和管理系统服务。 而在自定义Dockerfile构建的镜像中,PID为1的进程通常是Dockerfile最后指定的主应用进程,这导致无法正确处理僵尸进程。

解决方案

  1. 在启动容器时添加--init参数:
docker run --init your-image
  1. docker-compose.yml中配置:
version: '3'
    services:
        your-service:
            image: your-image
            init: true

补充说明

使用--init参数后,Docker会在容器中运行一个轻量级的init进程(通常是tini),作为PID 1运行,负责正确处理信号、清理僵尸进程、确保子进程正确退出。