在Elastic Beanstalk(Amazon Linux 2023)上使用Puppeteer生成PDF时遭遇‘Could not find Chrome’错误的可靠解决方法求助
在Elastic Beanstalk(Amazon Linux 2023)上使用Puppeteer生成PDF时遭遇‘Could not find Chrome’错误的可靠解决方法
我最近在Node.js应用里用Puppeteer生成PDF发票,本地测试完全正常,但部署到基于Amazon Linux 2023的Elastic Beanstalk(EB)时,一直碰到Chrome找不到的错误。之前用第三方脚本安装Chrome经常导致EB部署卡住超时,折腾了好几天终于找到稳定的解决方案,分享给同样踩坑的朋友:
我的问题背景
本地运行时,Puppeteer能自动找到Chrome,生成PDF毫无问题。但部署到EB后,要么部署过程卡在安装Chrome的步骤,要么部署成功后调用PDF生成接口时,Puppeteer报错“Could not find Chrome”。
我之前的Puppeteer代码
const puppeteer = require('puppeteer'); const fs = require('fs'); const path = require('path'); function fillTemplate(html, data) { return html.replace(/{{(.*?)}}/g, (_, key) => data[key.trim()] ?? ''); } async function generateInvoicePDF(filledHtml, outputFileName) { const browser = await puppeteer.launch({ headless: true, executablePath: '/usr/bin/google-chrome', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage' ] }); const page = await browser.newPage(); await page.setContent(filledHtml, { waitUntil: 'networkidle0' }); const logoBase64 = fs.readFileSync('./public/icon.png', { encoding: 'base64' }); await page.pdf({ path: outputFileName, format: 'A4', printBackground: true, displayHeaderFooter: true, margin: { top: '60px', bottom: '60px', left: '15mm', right: '15mm' } }); await browser.close(); return outputFileName; }
我之前踩坑的EB配置
# .ebextensions/01_install_chrome.config commands: 01_install_chrome: command: "curl https://intoli.com/install-google-chrome.sh | bash"
这个脚本经常因为网络波动或者执行步骤过多,导致EB部署超时卡住,即使偶尔成功,Puppeteer还是会莫名找不到Chrome。
可靠的解决步骤
1. 改用Amazon Linux 2023官方RPM安装Chrome
放弃第三方脚本,直接用Google官方的RPM包安装,EB的packages.rpm机制会自动处理依赖和安装逻辑,更稳定。
修改.ebextensions/01_install_chrome.config为:
packages: rpm: google-chrome-stable: https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm commands: # 创建软链接,确保和代码里的executablePath一致 01_create_chrome_symlink: command: ln -sf /usr/bin/google-chrome-stable /usr/bin/google-chrome test: '[ ! -f /usr/bin/google-chrome ]' # 安装Chrome无头运行必需的系统依赖 02_install_system_deps: command: dnf install -y atk cups-libs gtk3 libXcomposite alsa-lib libXcursor libXdamage libXext libXi libXrandr libXScrnSaver libXtst pango at-spi2-atk libXt xorg-x11-server-Xvfb xorg-x11-xauth dbus-glib dbus
为什么这样做?
- 官方RPM包的安装过程更可控,不会像第三方脚本那样有多余的步骤导致超时
- 补充的系统依赖是Chrome无头模式运行的必要条件,缺失的话即使Chrome安装了也无法启动
- 软链接保证代码里的
/usr/bin/google-chrome路径有效
2. 优化Puppeteer启动参数
针对EB的资源限制和环境,调整Puppeteer的启动选项,尤其是无头模式和资源相关的参数:
const browser = await puppeteer.launch({ headless: 'new', // Puppeteer v19+推荐使用新版无头模式,兼容性更好 executablePath: '/usr/bin/google-chrome', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', // 解决EB实例/dev/shm空间不足的问题 '--disable-gpu', // 无头模式不需要GPU '--no-zygote', // 减少进程数,降低资源占用 '--single-process', '--disable-features=VizDisplayCompositor' // 避免部分环境下的渲染问题 ] });
关键说明:
headless: 'new'是Puppeteer的新版无头模式,比旧的headless: true更接近真实Chrome的行为,减少兼容性问题--disable-dev-shm-usage会让Chrome用临时文件代替/dev/shm,EB实例的/dev/shm默认很小,容易导致Chrome崩溃
3. 修正静态文件路径
EB部署后,应用的根目录可能和本地不同,用相对路径读取文件容易出错,建议用path.resolve获取绝对路径:
// 替换原来的fs.readFileSync路径 const logoPath = path.resolve(__dirname, './public/icon.png'); const logoBase64 = fs.readFileSync(logoPath, { encoding: 'base64' });
这一步虽然不是Chrome找不到的直接原因,但能避免PDF生成时的资源加载错误,保证最终PDF的完整性。
验证方案有效性
- 重新部署EB应用:这次部署不会再超时卡住,因为RPM安装比脚本快且稳定
- 登录EB实例,执行
google-chrome --version,确认Chrome已成功安装 - 调用PDF生成接口,应该能正常生成PDF,不会再报“Could not find Chrome”的错误
额外注意事项
- 如果你使用的是
puppeteer-core,请确保版本和安装的Chrome版本兼容(Puppeteer官方有版本对应表,尽量使用最新版的puppeteer-core) - 建议使用至少
t2.small以上的EB实例,t2.micro的资源可能不足以支撑Chrome无头模式运行 - 如果还是遇到权限问题,可以检查EB应用的运行用户(默认是
webapp)是否有执行Chrome的权限,官方RPM安装的Chrome默认是全局可执行的,一般没问题
内容来源于stack exchange
相关产品推荐
相关产品推荐

