在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
相关产品推荐
相关产品推荐

