You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在DigitalOcean容器运行FastAPI+Selenium时Chrome启动失败求助

FastAPI + Selenium在DigitalOcean容器中Chrome启动失败问题解决

问题描述

本地运行FastAPI项目时,Selenium爬取功能正常,但部署到DigitalOcean容器后,调用涉及Selenium的API时出现Chrome启动失败错误,/docs页面可正常访问。

错误日志

File "/usr/local/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 428, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fastapi/applications.py", line 276, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/applications.py", line 122, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/usr/local/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 718, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 66, in app
    response = await func(request)
               ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 237, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 163, in run_endpoint_function
    return await dependant.call(**values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/web/scb_getstatement_api/main.py", line 162, in get_statement
    resault = get_statementscb(session, username, password,login)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/web/scb_getstatement_api/main.py", line 106, in get_statementscb
    session = getscb_session(username, password)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/web/scb_getstatement_api/main.py", line 23, in getscb_session
    driver = webdriver.Chrome(options=chrome_options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/chrome/webdriver.py", line 84, in __init__
    super().__init__(
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/chromium/webdriver.py", line 104, in __init__
    super().__init__(
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 286, in __init__
    self.start_session(capabilities, browser_profile)
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 378, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 440, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py", line 245, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

原Dockerfile

FROM python:3
# Set working directory
WORKDIR /web/scb_getstatement_api

# Copy project files
COPY main.py ./
COPY requirements.txt ./

# Install dependencies
RUN pip install --no-cache-dir -r requirements.txt


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

RUN pip3 install selenium chromedriver-autoinstaller

RUN groupadd -r chrome && useradd -r -g chrome -G audio,video chrome \
    && mkdir -p /home/chrome && chown -R chrome:chrome /home/chrome
USER chrome

# Expose port for FastAPI
EXPOSE 5000

# Run the FastAPI server
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5006"]

解决方案

1. 补充Chrome无头模式必要启动参数

修改初始化ChromeDriver的代码,添加容器环境必需的配置:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_autoinstaller

def getscb_session(username, password):
    # 自动安装匹配版本的ChromeDriver
    chromedriver_autoinstaller.install()
    
    chrome_options = Options()
    # 核心必需参数
    chrome_options.add_argument("--headless=new")  # 新版无头模式,兼容Chrome 112+
    chrome_options.add_argument("--no-sandbox")  # 容器环境禁用沙箱,否则Chrome无法启动
    chrome_options.add_argument("--disable-dev-shm-usage")  # 避免容器/dev/shm内存不足
    chrome_options.add_argument("--remote-debugging-port=9222")  # 解决DevToolsActivePort文件缺失问题
    chrome_options.add_argument("--user-data-dir=/tmp/chrome-user-data")  # 指定可写的用户数据目录
    # 优化参数,减少资源占用
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--disable-extensions")
    chrome_options.add_argument("--disable-plugins")
    chrome_options.add_argument("--start-maximized")
    
    driver = webdriver.Chrome(options=chrome_options)
    # 后续业务代码...

2. 优化Dockerfile配置

调整Dockerfile,完善系统依赖、权限和镜像选择:

FROM python:3.11-slim  # 使用轻量稳定的slim镜像

# 设置工作目录
WORKDIR /web/scb_getstatement_api

# 安装Chrome运行必需的系统依赖库
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget gnupg2 ca-certificates \
    fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 \
    libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 \
    libgdk-pixbuf2.0-0 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 xdg-utils \
    && rm -rf /var/lib/apt/lists/*  # 清理缓存,减少镜像体积

# 添加Chrome源并安装稳定版
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
RUN apt-get update && apt-get install -y google-chrome-stable \
    && rm -rf /var/lib/apt/lists/*

# 复制项目文件
COPY main.py ./
COPY requirements.txt ./

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir selenium chromedriver-autoinstaller

# 创建Chrome用户并设置目录权限
RUN groupadd -r chrome && useradd -r -g chrome -G audio,video chrome \
    && mkdir -p /tmp/chrome-user-data /home/chrome \
    && chown -R chrome:chrome /tmp/chrome-user-data /home/chrome /web/scb_getstatement_api

USER chrome

# 暴露与CMD一致的端口
EXPOSE 5006

# 启动FastAPI服务
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5006"]

关键修改说明

  • --no-sandbox:容器环境下Chrome无法使用Linux沙箱机制,必须禁用才能启动
  • --disable-dev-shm-usage:容器默认的/dev/shm空间有限,禁用后Chrome会使用临时文件存储数据,避免崩溃
  • --remote-debugging-port:强制指定调试端口,解决DevToolsActivePort file doesn't exist错误
  • 系统依赖安装:补充Chrome运行所需的底层库,避免因缺失依赖导致启动失败
  • 目录权限调整:确保Chrome用户有权限访问临时目录和项目目录,避免读写权限错误

内容的提问来源于stack exchange,提问作者Theerastillhere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:29:53