背景
项目使用Playwright进行自动化测试。虽然Playwright官方提供了包含浏览器和环境资源的镜像,但由于其JDK版本为17,高于项目需求,我们决定基于Playwright官方镜像自行封装JDK环境和应用镜像。
问题描述
容器在正常运行一段时间后,通过top命令统计发现存在近千个Chrome的僵尸进程。在复现测试中,每次自动化测试会启动六个Chrome相关进程(具有父子关系),测试流程退出后会产生两个Chrome僵尸进程。这个问题在Playwright的GitHub项目中已有相关讨论。
问题原因
在Docker容器中,默认情况下缺少init进程。在Linux系统中,PID为1的init进程负责:系统初始化、启动系统服务、收养孤儿进程、处理僵尸进程、处理系统信号和管理系统服务。 而在自定义Dockerfile构建的镜像中,PID为1的进程通常是Dockerfile最后指定的主应用进程,这导致无法正确处理僵尸进程。
解决方案
- 在启动容器时添加
--init参数:
docker run --init your-image
- 在
docker-compose.yml中配置:
version: '3'
services:
your-service:
image: your-image
init: true
补充说明
使用--init参数后,Docker会在容器中运行一个轻量级的init进程(通常是tini),作为PID 1运行,负责正确处理信号、清理僵尸进程、确保子进程正确退出。