Docker部署Selenium Grid加载Chrome扩展报写入prefs文件失败
问题描述
在Docker环境中运行加载Chrome扩展的Selenium Grid时,会话创建失败抛出如下错误,相同代码在本地环境可正常运行,仅通过Docker启动远程驱动时触发报错:
Stopping driver service: Could not start a new session. Response code 500. Message: unknown error: failed to write prefs file
对应测试代码:
chrome_options = Options() chrome_options.add_argument("user-data-dir=/dev/shm/sale") unpacked_extension_path = '/dev/shm/sale/Default/Extensions/nkbihfbeogaeaoehlefnkodbefgpgknn/10.16.1_0' chrome_options.add_argument('--load-extension={}'.format(unpacked_extension_path)) driver = webdriver.Remote(command_executor='http://x.x.x.x:4444/wd/hub', options=chrome_options)
对应docker-compose配置:
sale_selenium: container_name: sale_selenium image: selenium/standalone-chrome:103.0.5060.53 volumes: - ../mounts/Extensions:/dev/shm/sale/Default/Extensions networks: - sale_network expose: - 4444 deploy: resources: limits: cpus: '0.40' memory: '2500M'
问题根因
- 核心原因是目录权限不匹配:Selenium官方Chrome镜像默认以非root用户
seluser运行,当前配置仅挂载了/dev/shm/sale/Default/Extensions单个子目录,上层的/dev/shm/sale、/dev/shm/sale/Default目录由Docker在挂载时自动创建,默认归属root用户,seluser无写入权限。Chrome启动时需要向用户数据目录写入prefs偏好配置文件,写入操作被拒绝就会抛出该错误。 - 本地环境无问题是因为本地执行脚本的用户对自定义的user-data-dir路径拥有完整读写权限,不存在容器场景下的用户隔离、权限映射问题。
解决方案
方案一:调整挂载规则与目录权限(生产/测试环境推荐)
不要单独挂载Extensions子目录,直接挂载整个Chrome用户数据目录,容器启动时提前修正目录归属权限,修改后的docker-compose配置如下:
sale_selenium: container_name: sale_selenium image: selenium/standalone-chrome:103.0.5060.53 volumes: # 直接挂载整个用户数据目录到宿主机,避免Docker自动创建上层目录带来的权限问题 - ../mounts/chrome_sale_data:/dev/shm/sale networks: - sale_network expose: - 4444 # 启动前先将目录权限授权给运行Chrome的seluser用户 entrypoint: ["sh", "-c", "sudo chown -R seluser:seluser /dev/shm/sale && /opt/bin/entry_point.sh"] deploy: resources: limits: cpus: '0.40' memory: '2500M'
配置完成后,提前将扩展文件放到宿主机../mounts/chrome_sale_data/Default/Extensions/nkbihfbeogaeaoehlefnkodbefgpgknn/10.16.1_0路径下,原有Python测试代码无需修改即可正常运行。
方案二:使用临时用户目录加载扩展
移除代码中固定user-data-dir的配置,让Selenium自动创建拥有完整权限的临时用户目录,注意传入的扩展路径必须是容器内可访问的路径(需要提前通过挂载将扩展文件放入容器),修改后的代码示例:
chrome_options = Options() # 移除固定user-data-dir配置,避免自定义路径的权限问题 unpacked_extension_path = '/container/path/to/extension/nkbihfbeogaeaoehlefnkodbefgpgknn/10.16.1_0' chrome_options.add_argument('--load-extension={}'.format(unpacked_extension_path)) driver = webdriver.Remote(command_executor='http://x.x.x.x:4444/wd/hub', options=chrome_options)
方案三:以root权限运行容器(仅本地临时调试可用,不推荐)
在docker-compose配置中添加root用户运行参数,关闭沙箱限制,该方式存在安全风险,禁止在生产环境使用:
sale_selenium: container_name: sale_selenium image: selenium/standalone-chrome:103.0.5060.53 user: root environment: - SE_OPTS=--no-sandbox volumes: - ../mounts/Extensions:/dev/shm/sale/Default/Extensions networks: - sale_network expose: - 4444 deploy: resources: limits: cpus: '0.40' memory: '2500M'
内容的提问来源于stack exchange,提问作者Malashenkov.ea
相关产品推荐
相关产品推荐

