Laravel 10中Spatie/Browsershot在Docker环境无法运行求助
我在Laravel 10项目中使用Spatie/Browsershot库生成PDF,但在Docker环境中始终无法正常工作,抛出以下异常。
错误信息
异常类:Spatie\Browsershot\Exceptions\CouldNotTakeBrowsershot
For some reason Chrome did not write a file at `example.pdf`. Command ======= [] Output ======
测试用控制器代码
我用以下两种写法测试,结果一致:
public function getPDF() { return Browsershot::html('<h1>Hello world!!</h1>')->save('example.pdf'); } // 另一种写法: public function getPDF() { return Browsershot::html('<h1>Hello world!!</h1>') ->setRemoteInstance('chrome', 9222) ->save('example.pdf'); }
Docker Compose配置
version: '3' services: phpfpm: container_name: '${APP_NAME}' build: args: user: '${WWWUSER}' uid: '${WWWGROUP}' context: ./docker dockerfile: Dockerfile working_dir: /var/www/html volumes: - ./:/var/www/html networks: - network_project depends_on: - mariadb restart: unless-stopped chrome: image: 'zenika/alpine-chrome:80' entrypoint: ["chromium-browser", "--headless", "--disable-gpu", "--disable-software-rasterizer", "--disable-dev-shm-usage", "--no-sandbox", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222"] ports: - "9222:9222" networks: - network_project nginx: image: nginx:latest networks: - network_project depends_on: - mariadb ports: - '127.0.0.1:${APP_PORT}:80' volumes: - ./docker/nginx/tkt.conf:/etc/nginx/conf.d/default.conf - ./:/var/www/html links: - phpfpm restart: unless-stopped redis: image: 'redis:alpine' ports: - '127.0.0.1:${FORWARD_REDIS_PORT:-6379}:6379' volumes: - 'redis_volume:/data' networks: - network_project healthcheck: test: [ "CMD", "redis-cli", "ping" ] retries: 3 timeout: 5s restart: unless-stopped mariadb: image: 'mariadb:10.7.4' ports: - '127.0.0.1:${FORWARD_DB_PORT:-3306}:3306' environment: MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' MYSQL_DATABASE: '${DB_DATABASE}' MYSQL_USER: '${DB_USERNAME}' MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' volumes: - 'mariadb_volume:/var/lib/mysql' networks: - network_project healthcheck: test: [ "CMD", "mysqladmin", "ping" ] restart: unless-stopped mailhog: image: mailhog/mailhog networks: - network_project ports: - "1025:1025" - "8025:8025" restart: unless-stopped networks: network_project: driver: bridge volumes: mariadb_volume: driver: local redis_volume: driver: local
补充信息
- 已全局安装puppeteer.js:
npm install -g puppeteer - 已安装chromium:
npm install chromium - 应用环境:
- Laravel 10(PHP 8.2)
- InertiaJS
解决建议
检查容器间网络连通性
在phpfpm容器内执行ping chrome,确认能解析到chrome容器IP;再尝试访问http://chrome:9222/json/version,查看Chrome远程调试接口是否正常响应。确认文件写入权限
检查example.pdf的保存路径是否有写入权限,建议使用Laravel的存储路径代替根目录,比如:->save(storage_path('app/public/example.pdf'))同时确保存储目录的权限正确,可在phpfpm容器内执行
chmod -R 775 storage临时测试。更新Chrome镜像版本
当前使用的zenika/alpine-chrome:80版本过旧,可能与Laravel 10、PHP 8.2存在兼容性问题,建议更换为最新稳定版,比如zenika/alpine-chrome:latest或指定更高版本号。配置Browsershot指定Chrome路径
如果在phpfpm容器内安装了Chrome,需要在Browsershot中指定Chrome可执行文件路径:Browsershot::html('<h1>Hello world!!</h1>') ->setChromePath('/usr/bin/chromium-browser') ->save(storage_path('app/public/example.pdf'));若使用远程Chrome实例,确保
setRemoteInstance的地址是容器服务名chrome而非localhost,因为容器内localhost指向自身,无法访问外部的Chrome容器。查看Browsershot详细日志
开启Browsershot的调试模式,查看完整错误输出:Browsershot::html('<h1>Hello world!!</h1>') ->setRemoteInstance('chrome', 9222) ->setDebug(true) ->save('example.pdf');调试模式会输出完整的命令和错误详情,有助于定位问题。
内容的提问来源于stack exchange,提问作者Gaël Duval

