M1 Mac下Docker容器中Puppeteer运行newPage报Target closed如何解决
问题根因
一共三个核心问题导致报错:
- 业务代码中Puppeteer启动参数存在语法错误,容器环境必需的
--no-sandbox等参数未实际传入,Chromium以root身份启动后直接崩溃 - Alpine镜像内Chromium缺少必要运行依赖,启动后进程异常退出
- Docker默认共享内存过小,M1芯片模拟amd64架构运行时缺少适配参数,加剧了进程崩溃问题
修复步骤
1. 修正业务代码的Puppeteer启动配置
你之前的args配置缺少数组开头的左方括号,导致除了第一个参数外,其余启动参数都没有生效,这是触发报错的最核心原因。修正后的crawler.ts启动配置如下:
import puppeteer from 'puppeteer'; export const crawler = async (url: string) => { console.log(url); const browser = await puppeteer.launch({ ignoreHTTPSErrors: false, executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/chromium-browser', headless: true, // 注意这里数组括号必须写全,补全容器环境必需的启动参数 args: [ '--disable-dev-shm-usage', '--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu', '--disable-software-rasterizer', '--disable-extensions' ], slowMo: 30 }); console.log(browser) const page = await browser.newPage(); console.log(page); await page.setViewport({ width: 1920, height: 1080 }) await page.goto("https://www.example.com"); await page.close(); await browser.close(); };
2. 补全Dockerfile内Chromium的运行依赖
原Dockerfile只安装了极少量依赖,Alpine环境下Chromium运行需要额外的系统库,修正后的Dockerfile如下:
FROM node:18-alpine WORKDIR /usr/src/app RUN apk update && apk upgrade # 补全Chromium所有必需依赖 RUN apk add --no-cache \ chromium \ nss \ freetype \ harfbuzz \ ca-certificates \ ttf-freefont \ udev \ ttf-liberation ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true \ PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 这里和docker-compose的端口映射保持一致,你之前两个配置端口不一致 EXPOSE 8010 CMD ["npm", "run", "start:dev"]
3. 调整docker-compose配置
增加共享内存大小配置,避免Chromium运行时内存不足崩溃:
version: "3.7" services: node: container_name: node-test build: context: . dockerfile: Dockerfile restart: always platform: linux/amd64 # 增加共享内存配置,避免Chromium内存不足 shm_size: '1gb' extra_hosts: - "host.docker.internal:host-gateway" networks: - test-net env_file: - .env ports: - "8010:8010" depends_on: - mongo mongo: image: mongo container_name: mongo restart: always networks: - test-net ports: - "27017:27017" environment: MONGO_INITDB_ROOT_USERNAME: test MONGO_INITDB_ROOT_PASSWORD: test MONGO_INITDB_DATABASE: test volumes: mongo: networks: test-net: name: test-net external: true
验证方式
- 重新构建镜像,禁用缓存避免旧代码生效:
docker-compose build --no-cache node
- 启动容器后先在容器内手动验证Chromium是否可正常运行:
docker exec -it node-test /usr/bin/chromium-browser --headless --no-sandbox --dump-dom https://example.com
如果命令能正常输出example.com的DOM内容,说明Chromium环境正常,此时再调用业务接口就不会再报Target closed错误。
如果还是存在版本兼容问题,可以把项目内的
puppeteer依赖替换为puppeteer-core,避免内置的Chromium版本和容器内安装的Chromium版本不匹配。
内容的提问来源于stack exchange,提问作者penetrator.go
相关产品推荐
相关产品推荐

