如何在 Docker 中使用 Chrome 运行 Selenium

Posted

技术标签:

【中文标题】如何在 Docker 中使用 Chrome 运行 Selenium【英文标题】:How To Run Selenium With Chrome In Docker 【发布时间】:2018-01-01 13:24:50 【问题描述】:

我在Docker 中安装了google-chrome,但是当我运行Selenium 的Python 2 脚本时,它失败了:

automation@1c17781fef0c:/topology-editor/test$ python test.py
Traceback (most recent call last):
  File "test.py", line 27, in <module>
    browser = webdriver.Chrome()
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/chrome/webdriver.py", line 69, in __init__
    desired_capabilities=desired_capabilities)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 98, in __init__
    self.start_session(desired_capabilities, browser_profile)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 185, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 249, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: crashed
  (Driver info: chromedriver=2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8),platform=Linux 4.4.0-83-generic x86_64)

如果我直接在 docker 中运行 google-chrome,它会显示如下:

automation@1c17781fef0c:/topology-editor/test$ google-chrome
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted
Trace/breakpoint trap (core dumped)
automation@1c17781fef0c:/topology-editor/test$

系统:

$ uname -a
Linux 1c17781fef0c 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ google-chrome --version
Google Chrome 60.0.3112.78
$ chromedriver --version
ChromeDriver 2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8)

【问题讨论】:

你做到了吗? @lub0v 有 2 个 choci 可以在 docker:1 中运行 chrome。使用来自硒的selenium/standalone-chrome。 2. 构建Dockerfile并安装chrome,使用headless方式运行浏览器 github.com/joyzoursky/docker-python-chromedriver 【参考方案1】:

我假设你需要在无头模式下运行它

https://developers.google.com/web/updates/2017/04/headless-chrome

这就是我在 ruby​​ 中的做法

capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: args: %w[ no-sandbox headless disable-gpu window-size=1280,1000 ])

Capybara::Selenium::Driver.new(app, :browser => :chrome, http_client: client, desired_capabilities: capabilities)

您几乎可以在 python 中调整您的代码

还可以考虑安装一些 chrome 需要在 headless 上运行的字体库

RUN apt-get update && \
    apt-get -qq -y install  libxpm4 libxrender1 libgtk2.0-0 libnss3\ 
       libgconf-2-4  libpango1.0-0 libxss1 libxtst6 fonts-liberation\ 
       libappindicator1 xdg-utils

RUN apt-get -y install \
               xvfb gtk2-engines-pixbuf \
               xfonts-cyrillic xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable \
               imagemagick x11-apps zip

【讨论】:

【参考方案2】:

您需要启动一个独立的 chrome 浏览器

docker run -d -p 4444:4444 selenium/standalone-chrome

然后在你的 python 脚本中使用远程 webdriver 启动浏览器

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", DesiredCapabilities.CHROME)

如果您愿意,也可以启动 Selenium Grid 中心。

要作为 django 测试执行以下操作:

# docker-compse.yml

selenium:
  image: selenium/standalone-firefox
  ports:
  - 4444:4444

# project/app/test.py

from django.test import TestCase
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


class SiteTest(TestCase):
    fixtures = [
        'app/fixtures/app.json',
        ...
    ]

    def setUp(self):
        self.browser = webdriver.Remote("http://selenium:4444/wd/hub", DesiredCapabilities.FIREFOX)

    def tearDown(self):
        self.browser.quit()

    def test_visit_site(self):
        self.browser.get('http://app:8000/')
        self.assertIn(self.browser.title, 'Home')

注意:

如果您使用webdriver.ChromeOptions|FirefoxOptions|etc,则无需导入DesiredCapabalities

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')  # example
driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", options=options)

【讨论】:

我已经尝试使用 selenium/standalone-chrome 成功运行。我失败了,因为我想将 chrome/selenium 与我们之前使用的另一个 docker 图像集成。我会尝试远程运行方式,谢谢。 在不同的地方进行大量搜索后,我发现这是最适合我的答案 有人帮我理解为什么远程链接是“127.0.0.1”? @MertTheGreat,这是由其他人更新的,但 127.0.0.1 只是一个例子。在 docker 中是selenium 它对我有用,因为我看到拥有我的应用程序的容器已连接到 selenium 容器,但 chrome UI 没有显示,我没有将它置于无头模式并且有没有错误,我错过了什么吗?【参考方案3】:

您需要在 Dockerfile 中添加下一行:

# install google chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable

# install chromedriver
RUN apt-get install -yqq unzip
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/

# set display port to avoid crash
ENV DISPLAY=:99

# install selenium
RUN pip install selenium==3.8.0

那么你的代码应该是这样的。特别是你需要像下面这样声明你的driver

from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)

driver.get('www.google.com')
screenshot = driver.save_screenshot('test.png')
driver.quit()

【讨论】:

使用chrome_options 为您的配置做的很好,可以在 headless 模式下启动 chrome 感谢您的回答!我还提到可以改进 Dockerfile 以遵循docs.docker.com/develop/develop-images/… 并产生更少的层/更少的大小。例如,所有 RUN 指令可以合并为一条。此外,我们不需要将 /tmp/chromedriver.zip 文件作为图像的一部分,我们可以在解压缩后将其删除。两个 apt-get install 命令可以合二为一。 我喜欢您下载屏幕截图的方式,因此可以看到它确实在工作 它解决了很多问题,但它仍然对我不起作用。我的脚本不仅仅是截屏,我猜这会引入各种新问题。首先是选项卡崩溃问题,如果你解决了这个问题,那么你就会遇到超时问题。 值得更明确,因为我有这个问题,但后来解决了... dockerfile 的第一行应该是 FROM python:latest【参考方案4】:

对于通过谷歌搜索的人来说,这是最简单的解决方法:

Dockerfile

FROM python:3.7

RUN apt-get update 
RUN apt-get install -y gconf-service libasound2 libatk1.0-0 libcairo2 libcups2 libfontconfig1 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libxss1 fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils

#download and install chrome
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb; apt-get -fy install

#install python dependencies
COPY requirements.txt requirements.txt 
RUN pip install -r ./requirements.txt 

#some envs
ENV APP_HOME /app 
ENV PORT 5000

#set workspace
WORKDIR $APP_HOME

#copy local files
COPY . . 

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 main:app 

您需要安装我在requirements.txt 中添加的chromedriver_binary pip 包:

Flask==1.1.1
gunicorn==20.0.4
selenium==3.141.0
chromedriver-binary==79.0.3945.36

那么你的main.py 应该是这样的:

from selenium import webdriver
import chromedriver_binary


chrome_options=webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("window-size=1400,2100") 
chrome_options.add_argument('--disable-gpu')

driver=webdriver.Chrome(chrome_options=chrome_options)

现在,使用 docker build -t &lt;imagename&gt; .docker run --rm -p &lt;yourPORT&gt;:5000 &lt;imagename&gt; 构建您的 Dockerfile

【讨论】:

仅供参考,您需要更新 chromedriver-binary 以匹配当前稳定的 chrome 版本,否则当您尝试运行“消息:会话未创建:此版本的 ChromeDriver 仅支持 Chrome 版本 79 " 是的@LeonKyriacou 我同意。以下是我如何自动化 google chrome 和 chromedriver 之间的版本匹配: wget -O LATEST_RELEASE chromedriver.storage.googleapis.com/LATEST_RELEASE && \ latest=$(cat LATEST_RELEASE) && \ sed -i "s/XXXX/$latest/g" requirements.txt && \

以上是关于如何在 Docker 中使用 Chrome 运行 Selenium的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 chrome-headless 在 docker 中运行 angular-cli 业力测试

Rod 在 Docker Alpine 中运行得到错误“chrome-linux/chrome:没有这样的文件或目录”

经过测试,chrome 进程仍然在 Docker 容器中的 Laravel Dusk

在docker-compose中运行python selenium

无法在 docker 中运行 chromedp

Docker 容器在您的平台上为 Chrome 浏览器提供无二进制文件