Исправление сбоя Selenium ChromeDriver в Docker-контейнерах
Узнайте, почему Selenium ChromeDriver вылетает в Docker-контейнерах и найдите проверенные решения. Исправьте ошибки обработчика crashpad, проблемы с разделяемой памятью и ограничения безопасности песочницы с помощью подробного руководства по устранению неполадок.
Почему мой Selenium ChromeDriver падает при запуске в Docker?
Я столкнулся с проблемой, когда мой Selenium ChromeDriver падает при развертывании в Docker-контейнере. Тот же код отлично работает на моем локальном компьютере без Docker, но не работает при контейнеризации.
Вот логи ошибок из Docker-окружения:
[1762419439.089][INFO]: Starting ChromeDriver 142.0.7444.59 (4b8153ab58d3c3f4c9f7e4baad9616ecf80db5fa-refs/branch-heads/7444_52@{#4}) on port 51133
[1762419439.089][INFO]: Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
[1762419439.094][INFO]: ChromeDriver was started successfully on port 51133
[1762419439.156][INFO]: [80ba8e74f3788cef64c7519d1352cb64] COMMAND InitSession {
"capabilities": {
"alwaysMatch": {
"browserName": "chrome",
"goog:chromeOptions": {
"args": [ "--headless", "--no-sandbox", "--disable-dev-shm-usage", "--user-data-dir=/tmp/chrome-user-data" ],
"extensions": [ ]
},
"pageLoadStrategy": "normal"
},
"firstMatch": [ {
} ]
}
}
[1762419439.156][INFO]: Browser search. Trying... /usr/bin/chromium
[1762419439.156][INFO]: Browser search. Found at /usr/bin/chromium
[1762419439.157][INFO]: Populating Preferences file: {
"alternate_error_pages": {
"enabled": false
},
"autofill": {
"enabled": false
},
"browser": {
"check_default_browser": false
},
"distribution": {
"import_bookmarks": false,
"import_history": false,
"import_search_engine": false,
"make_chrome_default_for_user": false,
"skip_first_run_ui": true
},
"dns_prefetching": {
"enabled": false
},
"profile": {
"content_settings": {
"pattern_pairs": {
"https://*,*": {
"media-stream": {
"audio": "Default",
"video": "Default"
}
}
}
},
"default_content_setting_values": {
"geolocation": 1
},
"default_content_settings": {
"geolocation": 1,
"mouselock": 1,
"notifications": 1,
"popups": 1,
"ppapi-broker": 1
},
"password_manager_enabled": false
},
"safebrowsing": {
"enabled": false
},
"search": {
"suggest_enabled": false
},
"translate": {
"enabled": false
}
}
[1762419439.157][INFO]: Populating Local State file: {
"background_mode": {
"enabled": false
},
"ssl": {
"rev_checking": {
"enabled": false
}
}
}
[1762419439.157][INFO]: ChromeDriver supports communication with Chrome via pipes. This is more reliable and more secure.
[1762419439.157][INFO]: Use the --remote-debugging-pipe Chrome switch instead of the default --remote-debugging-port to enable this communication mode.
[1762419439.157][INFO]: Launching chrome: /usr/bin/chromium --allow-pre-commit-input --disable-background-networking --disable-client-side-phishing-detection --disable-default-apps --disable-dev-shm-usage --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 --test-type=webdriver --use-mock-keychain --user-data-dir=/tmp/chrome-user-data
chrome_crashpad_handler: --database is required
Try 'chrome_crashpad_handler --help' for more information.
[1305:1305:1106/085719.230136:ERROR:third_party/crashpad/crashpad/util/linux/socket.cc:120] recvmsg: Connection reset by peer (104)
[1762419439.372][INFO]: [80ba8e74f3788cef64c7519d1352cb64] RESPONSE InitSession ERROR session not created: Chrome instance exited. Examine ChromeDriver verbose log to determine the cause.
[1762419439.372][DEBUG]: Log type 'driver' lost 0 entries on destruction
[1762419439.372][DEBUG]: Log type 'browser' lost 0 entries on destruction
Мой FastAPI-сервис инициализирует ChromeDriver следующим образом:
def __init__(self):
# Initialize Chrome only once
if ContextService._driver is None:
with ContextService._lock:
if ContextService._driver is None: # Check again once locked
options = Options()
options.add_argument(
"--headless"
) # This makes the browser run in the background with NO GUI
options.add_argument("--no-sandbox")
options.add_argument(
"--disable-dev-shm-usage"
) # Use temporary directory instead of /dev/shm (may crash on Docker)
options.add_argument("--user-data-dir=/tmp/chrome-user-data")
if os.path.exists("/usr/bin/chromium"):
# Usage of chromium -> Docker (lighter)
service = Service(
"/usr/bin/chromedriver",
log_output="/tmp/chrome.log",
service_args=["--verbose"],
)
else:
# Usage of Chrome in local development
service = Service(ChromeDriverManager().install())
try:
ContextService._driver = webdriver.Chrome(
service=service, options=options
) # IT FAILS HERE!
ContextService._driver.set_page_load_timeout(30)
except WebDriverException as wde:
raise RuntimeError(f"Failed to start Chrome driver: {wde}")
Dockerfile, который я использую:
FROM python:3.13-slim AS builder
WORKDIR /usr/src/context-service
COPY pyproject.toml .
COPY ./app ./app
RUN pip install --no-cache-dir .
FROM python:3.13-slim
# Create non-root user
RUN addgroup --system nonroot && adduser --system nonroot --ingroup nonroot
# For this service, the HOME env variable is needed
ENV HOME=/home/nonroot
RUN mkdir -p "$HOME" && chown -R nonroot:nonroot "$HOME"
WORKDIR /usr/src/context-service
# Install Chromium + driver
RUN apt-get update && apt-get install -y ca-certificates chromium chromium-driver curl && rm -rf /var/lib/apt/lists/*
# Copy installed deps and app
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /usr/src/context-service/app ./app
# Copy and add permissions to execute the entrypoint (sets the certificates to be trusted)
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 8000
# Run as root (needed for CA update)
USER root
# Run the application from the shell script
ENTRYPOINT ["/entrypoint.sh"]
А мои зависимости в pyproject.toml включают:
"selenium>=4.22.0,<5.0",
"beautifulsoup4>=4.12.3,<5.0",
"webdriver-manager>=4.0.0,<5.0",
Я заметил, что в сообщении об ошибке упоминается, что для crashpad требуется --database, но то же самое сообщение появляется в логах, когда все работает на моем ПК. Что может вызывать падение ChromeDriver в Docker, и как это можно исправить?
Сбои ChromeDriver в контейнерах Docker — это распространенная проблема, вызванная ограниченной средой и ограничениями безопасности, которые накладывает Docker. На основании ваших логов ошибок и конфигурации сбой, по-видимому, связан с обработчиком crashpad Chrome, требующим параметр базы данных, а также с несколькими другими потенциальными факторами среды.
Содержание
- Общие причины сбоев ChromeDriver в Docker
- Ошибка обработчика crashpad
- Проблемы с разделяемой памятью
- Ограничения песочницы и безопасности
- Проблемы совместимости версий
- Отсутствующие зависимости
- Проблемы сети и подключения
- Решения и лучшие практики
Общие причины сбоев ChromeDriver в Docker
Сбои ChromeDriver в Docker обычно возникают из-за нескольких различий в среде между локальной разработкой и контейнеризированными средами. В проблемах docker-selenium от SeleniumHQ постоянно идентифицируются следующие наиболее частые причины:
- Ограниченная разделяемая память: Контейнеры Docker часто имеют ограниченный доступ к
/dev/shm - Ограничения безопасности песочницы: Контейнеры запускаются с ограниченными привилегиями
- Отсутствующие системные зависимости: Chrome требует определенные библиотеки, которые могут не быть включены в базовые образы Docker
- Несовместимости версий: Версии ChromeDriver и Chrome должны точно совпадать
Ошибка обработчика crashpad
Ваши логи показывают конкретную ошибку: chrome_crashpad_handler: --database is required. Это указывает на то, что система отчетов о сбоях Chrome неправильно настроена в вашей Docker-среде. Согласно соображениям безопасности ChromeDriver, на которые ссылаются ваши логи, это часто происходит, когда:
Обработчику crashpad требуется выделенный каталог базы данных для хранения отчетов о сбоях. В вашем Dockerfile вы устанавливаете Chromium, но не настраиваете каталог базы данных crashpad. Именно поэтому одна и та же ошибка появляется как при работающем, так и при аварийно завершающемся состоянии — обработчик crashpad присутствует, но неправильно настроен.
Проблемы с разделяемой памятью
Аргумент --disable-dev-shm-usage, который вы включаете, правильный и решает распространенную проблему Docker. Однако вам могут потребоваться дополнительные конфигурации:
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-software-rasterizer")
options.add_argument("--disable-background-timer-throttling")
Как отмечено в расследовании сбоев AWS Batch, ограничения разделяемой памяти часто вызывают сбои Chrome, особенно при запуске нескольких экземпляров.
Ограничения песочницы и безопасности
Аргумент --no-sandbox необходим для сред Docker, но вам могут потребоваться дополнительные аргументы, связанные с безопасностью:
options.add_argument("--no-sandbox")
options.add_argument("--disable-setuid-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-web-security")
options.add_argument("--disable-features=VizDisplayCompositor")
Согласно обсуждению в поддержке Zyte, эти аргументы помогают Chrome работать в рамках ограничений безопасности Docker.
Проблемы совместимости версий
Ваши логи показывают ChromeDriver версии 142.0.7444.59, но вы используете /usr/bin/chromium. Версии ChromeDriver и Chromium должны точно совпадать. Проверьте версии:
# Добавление проверки версии
chrome_version = subprocess.check_output(['chromium', '--version']).decode()
print(f"Версия Chromium: {chrome_version}")
В обсуждении на Stack Overflow подчеркивается, что несоответствия версий являются частой причиной сбоев.
Отсутствующие зависимости
Ваш Dockerfile устанавливает Chromium, но может отсутствовать некоторые важные зависимости. Рассмотрите возможность добавления:
RUN apt-get update && apt-get install -y \
ca-certificates \
chromium \
chromium-driver \
curl \
fonts-liberation \
libappindicator3-1 \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libc6 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libexpat1 \
libfontconfig1 \
libgbm1 \
libgcc1 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libstdc++6 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
lsb-release \
wget \
xdg-utils \
&& rm -rf /var/lib/apt/lists/*
Проблемы сети и подключения
Как упоминается в обсуждении подключения boot2docker, проблемы подключения могут вызывать сбои ChromeDriver. Убедитесь, что ваша конфигурация сети Docker позволяет Chrome правильно обмениваться данными.
Решения и лучшие практики
На основании результатов исследования, вот решения для исправления сбоев ChromeDriver:
1. Правильно настройте параметры Chrome
def __init__(self):
if ContextService._driver is None:
with ContextService._lock:
if ContextService._driver is None:
options = Options()
# Необходимые аргументы для Docker
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-software-rasterizer")
options.add_argument("--disable-setuid-sandbox")
options.add_argument("--disable-web-security")
options.add_argument("--disable-features=VizDisplayCompositor")
options.add_argument("--disable-background-timer-throttling")
options.add_argument("--disable-backgrounding-occluded-windows")
options.add_argument("--disable-renderer-backgrounding")
options.add_argument("--disable-ipc-flooding-protection")
options.add_argument("--disable-extensions")
options.add_argument("--disable-plugins")
options.add_argument("--disable-images")
options.add_argument("--disable-javascript")
options.add_argument("--user-data-dir=/tmp/chrome-user-data")
options.add_argument("--disable-crash-reporter")
options.add_argument("--disable-features=VizDisplayCompositor")
# Установка размера окна
options.add_argument("--window-size=1920,1080")
options.add_argument("--start-maximized")
# Установка пользовательского агента
options.add_argument("--user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36")
# Отключение логирования для уменьшения шума
options.add_argument("--log-level=3")
options.add_experimental_option("excludeSwitches", ["enable-logging"])
if os.path.exists("/usr/bin/chromium"):
service = Service(
"/usr/bin/chromedriver",
log_output="/tmp/chrome.log",
service_args=["--verbose", "--log-level=ALL"],
)
else:
service = Service(ChromeDriverManager().install())
try:
ContextService._driver = webdriver.Chrome(
service=service, options=options
)
ContextService._driver.set_page_load_timeout(30)
except WebDriverException as wde:
raise RuntimeError(f"Не удалось запустить Chrome driver: {wde}")
2. Обновите ваш Dockerfile
FROM python:3.13-slim AS builder
WORKDIR /usr/src/context-service
COPY pyproject.toml .
COPY ./app ./app
RUN pip install --no-cache-dir .
FROM python:3.13-slim
# Создание непривилегированного пользователя
RUN addgroup --system nonroot && adduser --system nonroot --ingroup nonroot
# Для этого сервиса нужна переменная окружения HOME
ENV HOME=/home/nonroot
RUN mkdir -p "$HOME" && chown -R nonroot:nonroot "$HOME"
WORKDIR /usr/src/context-service
# Установка Chromium + драйвера со всеми зависимостями
RUN apt-get update && apt-get install -y \
ca-certificates \
chromium \
chromium-driver \
curl \
fonts-liberation \
libappindicator3-1 \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libc6 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libexpat1 \
libfontconfig1 \
libgbm1 \
libgcc1 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libstdc++6 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
lsb-release \
wget \
xdg-utils \
&& rm -rf /var/lib/apt/lists/* \
&& ln -s /usr/bin/chromium-browser /usr/bin/chromium
# Создание каталога базы данных crashpad
RUN mkdir -p /tmp/chrome-crashpad && chmod 777 /tmp/chrome-crashpad
# Копирование установленных зависимостей и приложения
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /usr/src/context-service/app ./app
# Копирование и добавление прав на выполнение entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 8000
# Запуск от root (необходимо для обновления CA)
USER root
# Установка переменной окружения для базы данных crashpad
ENV CHROME_CRASHPAD_DATABASE=/tmp/chrome-crashpad
# Запуск приложения из shell-скрипта
ENTRYPOINT ["/entrypoint.sh"]
3. Обработка несоответствий версий Chrome/Chromium
Убедитесь, что ваша версия ChromeDriver соответствует версии Chromium. Вы можете добавить проверку версии:
import subprocess
from packaging import version
def get_chrome_version():
try:
version_output = subprocess.check_output(['chromium', '--version']).decode()
return version_output.split(' ')[1]
except:
return None
def get_matching_chromedriver_version(chrome_version):
# Обычно это включает загрузку соответствующей версии ChromeDriver
# Пока просто вернем путь
return "/usr/bin/chromedriver"
# Использование в __init__:
chrome_version = get_chrome_version()
if chrome_version:
print(f"Используется версия Chromium: {chrome_version}")
# Здесь может потребоваться загрузка соответствующей версии ChromeDriver
4. Альтернатива: использование официальных Docker-образов Selenium
Рассмотрите возможность использования официальных Docker-образов Selenium вместо сборки собственного:
FROM selenium/standalone-chrome:latest
# Установка Python и вашего приложения
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install fastapi selenium beautifulsoup4 webdriver-manager
COPY ./app /app
WORKDIR /app
COPY requirements.txt .
RUN pip3 install -r requirements.txt
EXPOSE 8000
CMD ["python3", "main.py"]
Источники
- SeleniumHQ docker-selenium - Headless chrome is not working in the docker
- Chrome crashes no matter what in Selenium docker image - Google Groups
- Docker container with Selenium and Chrome webdriver crashes when multiple containers run in parallel on AWS Batch - Stack Overflow
- Selenium webdriver, chromedriver and chrome with docker image failed by crashing Chrome - Zyte Support
- Headless chrome with Selenium and Java in a Docker container - Stack Overflow
- Docker: using container with headless Selenium Chromedriver - Stack Overflow
- SeleniumHQ selenium - Chrome failed to start: crashed - GitHub
- SeleniumHQ docker-selenium - session deleted because of page crash - GitHub
- Google chrome is getting crashed when running selenium tests on docker - Docker Community Forums
Заключение
Сбои ChromeDriver в Docker обычно вызваны ограничениями среды и отсутствующими конфигурациями. На основании ваших логов ошибок и результатов исследования:
- Ошибка обработчика crashpad является основной проблемой — Chrome требует каталог базы данных crashpad, который должен быть настроен в вашей Docker-среде
- Ограничения разделяемой памяти требуют
--disable-dev-shm-usageи, возможно, дополнительных конфигураций памяти - Ограничения безопасности песочницы требуют
--no-sandboxи связанных флагов - Отсутствующие зависимости в вашем Docker-образе могут вызывать сбой Chrome при запуске
- Совместимость версий между ChromeDriver и Chromium должна обеспечиваться
Наиболее эффективным решением является обновление вашего Dockerfile для включения всех необходимых зависимостей, настройка каталога базы данных crashpad и расширение параметров Chrome дополнительными аргументами, специфичными для Docker. Если вы продолжаете испытывать проблемы, рассмотрите возможность использования официальных Docker-образов Selenium, которые специально оптимизированы для запуска Chrome в контейнеризированных средах.