如何以非seluser用户正确运行Selenium standalone-chrome容器?
解决Selenium独立Chrome容器非默认用户运行及文件下载权限问题
问题背景
使用Python + selenium/standalone-chrome实现网站.xlsx文件自动化下载,已将两个容器配置在同一Docker网络并共享volume:
docker run -d -v selenium_vol:/home/myuser/Downloads -p 4444:4444 -p 7900:7900 --name download_cont --network test_net --shm-size="2g" selenium/standalone-chrome docker run -d -v selenium_vol:/usr/src/app/download_folder --network test_net --name python_auto automation
发现仅当selenium_vol关联的本地文件夹权限设为777时,Selenium容器才能正常下载,否则提示权限不足。为避免777权限,尝试创建与本地机器UID/GID(均为1000)匹配的myuser并自定义Dockerfile,但运行Python代码时触发SessionNotCreatedException。
自定义Dockerfile及报错详情
自定义Dockerfile
FROM selenium/standalone-chrome:latest # Adding the group and the user for security reinforcement purpose RUN sudo groupadd -o --gid 1000 myuser RUN sudo useradd -o --uid 1000 --gid myuser --shell /bin/sh --create-home myuser # Adding the folder in which the program will be copied and called RUN sudo mkdir /home/myuser/Downloads RUN sudo chown -R myuser:myuser /home/myuser/Downloads RUN sudo chmod 777 /home/myuser/Downloads # Changing directory WORKDIR /home/myuser/Downloads # Copying all the files, and changing the ownership to the new user, myuser COPY --chown=myuser:myuser . . # Changing the user to the one we created before, with limited access to the machine: myuser USER myuser
报错的Python代码
options = webdriver.ChromeOptions() options.add_argument('--no-sandbox') options.add_argument("--disable-dev-shm-usage") prefs = { "download.default_directory": "/home/myuser/Downloads/", "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True } driver = webdriver.Remote(command_executor="http://localhost:4444", options=options) try: driver.set_page_load_timeout(120) driver.set_script_timeout(120) driver.implicitly_wait(120) print(driver.session_id) driver.command_executor._commands["send_command"] = ( "POST", '/session/' + driver.session_id + '/chromium/send_command') params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': '/home/myuser/Downloads/'}} command_result = driver.execute("send_command", params) my_function(driver) driver.quit() except Exception as e: print(e) driver.quit()
报错信息
Traceback (most recent call last): File "Drive:\my_automation_test\main.py", line 149, in <module> driver = webdriver.Remote(command_executor="http://localhost:4444", options=options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "Drive:\my_automation_test\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 208, in __init__ self.start_session(capabilities) File "Drive:\my_automation_test\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 292, in start_session response = self.execute(Command.NEW_SESSION, caps)["value"] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "Drive:\my_automation_test\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 347, in execute self.error_handler.check_response(response) File "Drive:\my_automation_test\.venv\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 229, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.SessionNotCreatedException: Message: Could not start a new session. No nodes support the capabilities in the request Host info: host: 'host-id', ip: 'xxx.xxx.xxx.xxx' Build info: version: 'ver', revision: 'revision-id' System info: os.name: 'Linux', os.arch: 'amd64', os.version: 'os-version', java.version: '17.0.12' Driver info: driver.version: unknown Stacktrace: at org.openqa.selenium.grid.distributor.local.LocalDistributor$NewSessionRunnable.checkMatchingSlot (LocalDistributor.java:816) at org.openqa.selenium.grid.distributor.local.LocalDistributor$NewSessionRunnable.run (LocalDistributor.java:798) at org.openqa.selenium.concurrent.GuardedRunnable.lambda$guard$0 (GuardedRunnable.java:35) at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539) at java.util.concurrent.FutureTask.runAndReset (FutureTask.java:305) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136) at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635) at java.lang.Thread.run (Thread.java:840) Process finished with exit code 1
解决方案
1. 修改默认seluser的UID/GID(推荐)
selenium/standalone-chrome容器默认使用seluser运行Selenium Grid服务和Chrome,直接切换到自定义用户会导致服务启动失败(容器内服务配置、权限均基于seluser)。正确做法是修改seluser的UID/GID匹配本地用户,而非新建用户:
修改后的Dockerfile:
FROM selenium/standalone-chrome:latest # 修改seluser的UID和GID为本地用户的1000 RUN sudo usermod -u 1000 seluser && sudo groupmod -g 1000 seluser # 确保Downloads目录权限正确 RUN sudo chown -R seluser:seluser /home/seluser/Downloads
2. 调整容器启动命令和Python代码
- 启动Selenium容器时,挂载volume到默认的
/home/seluser/Downloads:
docker run -d -v selenium_vol:/home/seluser/Downloads -p 4444:4444 -p 7900:7900 --name download_cont --network test_net --shm-size="2g" your-custom-selenium-image
- 修改Python代码中的下载路径:
prefs = { "download.default_directory": "/home/seluser/Downloads/", "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True } # ... params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': '/home/seluser/Downloads/'}}
3. 本地目录权限配置
确保本地挂载的目录UID/GID为1000(和容器内seluser一致),无需设置777:
# 假设本地目录是./selenium_downloads sudo chown -R 1000:1000 ./selenium_downloads sudo chmod 755 ./selenium_downloads
4. Docker Compose简化配置(可选)
用docker-compose.yml整合两个容器配置,避免手动输入命令:
version: '3.8' services: selenium-chrome: build: . # 指向自定义Dockerfile所在目录 ports: - "4444:4444" - "7900:7900" volumes: - selenium_vol:/home/seluser/Downloads networks: - test_net shm_size: "2g" python-auto: image: automation volumes: - selenium_vol:/usr/src/app/download_folder networks: - test_net depends_on: - selenium-chrome volumes: selenium_vol: networks: test_net: driver: bridge
关键说明
- 不要替换容器默认运行用户:selenium/standalone-chrome的启动脚本、服务依赖都是基于seluser配置的,切换用户会导致Grid服务无法初始化,进而引发
SessionNotCreatedException。 - 权限匹配核心:让容器内运行Chrome的用户(seluser)UID/GID和本地目录的所有者一致,即可避免777权限。
内容的提问来源于stack exchange,提问作者Persifer
相关产品推荐
相关产品推荐

