容器化中运行 Playwright并驱动 Chrome
方案一:使用 Playwright 官方镜像(推荐)
Playwright 官方团队维护了包含完整环境的 Docker 镜像,里面已经内置了 Node.js/Python 环境以及所有浏览器运行所需的依赖,是最不容易踩坑的方案。
1. 选择镜像
根据你使用的编程语言,拉取对应的官方镜像:
- Node.js:
mcr.microsoft.com/playwright:v1.61.0-noble - Python:
mcr.microsoft.com/playwright/python:v1.60.0-noble
2. 编写代码(以 Python 为例)
在代码中,如果你想明确指定驱动 Google Chrome(而非 Playwright 默认的开源 Chromium),可以通过设置 channel="chrome" 来实现。
1 | from playwright.sync_api import sync_playwright |
方案二:在自定义基础镜像中安装
如果你必须基于公司现有的 Linux 基础镜像(如 ubuntu 或 debian)进行构建,可以参考以下 Dockerfile 配置。
注意: 极度不建议使用
alpine镜像,因为 Playwright 的浏览器二进制文件是为glibc编译的,在 Alpine 的musl环境下极难跑通。
1. 编写 Dockerfile(Python 示例)
1 | FROM python:3.11-slim-bookworm |
2. 编写 Dockerfile(Node.js 示例)
1 | FROM node:20-bookworm-slim |
踩坑与优化指南
在容器内跑 Chrome,以下几点如果没配置好,程序大概率会报错或频繁崩溃:
1. 共享内存不足导致崩溃(/dev/shm)
Docker 容器默认分配的共享内存通常只有 64MB,当 Chrome 打开较复杂的网页时,会因为内存耗尽而直接崩溃(报错通常为 Target closed 或 Crash)。
- 解决方案:在启动 Docker 容器时,必须加上
--ipc=host参数,允许容器共享宿主机的内存。
1 | docker run -it --rm --ipc=host my-playwright-app |
2. Chrome 沙盒权限问题(Sandbox)
Linux 的 Chromium/Chrome 默认使用沙盒机制保障安全,但在 Docker 容器中(尤其是以 root 用户运行时),沙盒往往会因为没有内核权限而报错。
- 临时解决(信任代码):在代码启动浏览器时,添加启动参数
args=["--no-sandbox", "--disable-setuid-sandbox"]。 - 标准解决(抓取不信任网站):Playwright 官方镜像内置了一个名为
pwuser的非 root 用户。推荐在 Dockerfile 中切换到该用户,或者在运行容器时使用安全配置文件(seccomp)。
3. 无头模式(Headless)
在没有安装 X11 桌面环境的 Linux 容器中,必须以无头模式运行 Chrome:
1 | browser = p.chromium.launch(headless=True) |
如果你确实需要有头模式(Headless=False)来调试或截图,你需要在 Docker 内部部署并启动 Xvfb(虚拟帧缓冲区),利用 xvfb-run python main.py 来欺骗 Chrome 拥有显示器。