docker-selenium:基于 Docker 的 Selenium Grid 服务器镜像项目

Provides a simple way to run Selenium Grid with Chrome, Firefox, and Edge using Container Platform, making it easier to perform browser automation at scale

分支26Tags435
文件最后提交记录最后更新时间
1 年前
1 个月前
19 天前
19 天前
2 个月前
19 天前
22 天前
21 天前
3 个月前
6 个月前
1 个月前
6 个月前
1 个月前
1 个月前
4 个月前
22 天前
21 天前
6 个月前
22 天前
1 个月前
2 个月前
22 天前
6 个月前
4 个月前
6 个月前
28 天前
22 天前
20 天前
2 个月前
19 天前
11 年前
3 个月前
4 年前
6 年前
2 个月前
6 年前
20 天前
22 天前
22 天前
22 天前
22 天前
9 个月前
9 个月前
22 天前
22 天前
22 天前
22 天前
22 天前
1 年前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
22 天前
1 年前
1 个月前
1 年前
5 年前
1 个月前
9 个月前
1 年前

构建与测试 部署 发布图表 每日构建 更新开发/测试版浏览器镜像 发布下载量 咨询DeepWiki

GitHub最后提交 GitHub发布 GitHub最新发布后提交数 GitHub提交活跃度 GitHub贡献者

Selenium Grid Server 的 Docker 镜像

本项目的实现离不开志愿者贡献者们投入的数千小时时间,源代码根据 Apache License 2.0 协议免费开放。

这些 Docker 镜像提供了多个标签以简化使用,您可以在我们的 发布版本 中查看这些标签。

如需获取新版本通知,请将自己设置为“仅发布”观察者。

这些镜像发布在 Docker Hub registry,地址为 Selenium Docker Hub

  • Hub:Docker 拉取次数
  • Node-Chrome:Docker 拉取次数
  • Standalone-Chrome:Docker 拉取次数

Helm Chart 支持在 Kubernetes 中创建 Selenium Grid Server,详情请见 Artifact Hub

社区

您在使用这些 Docker 镜像时需要帮助吗? 请通过 https://www.selenium.dev/support/ 与我们交流。

目录

系统推荐配置

  • Docker Engine 26.1.4 或更高版本
  • Docker Compose v2.34.0 或更高版本
  • Docker Buildx v0.25.0 或更高版本
  • Kubernetes v1.26.15 或更高版本

快速开始

  1. 使用 Firefox 启动 Docker 容器
docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:4.47.0-20260808
  1. 将您的 WebDriver 测试指向 http://localhost:4444

  2. 就是这样!

  3. (可选)要查看容器内部的情况,请访问 http://localhost:7900/?autoconnect=1&resize=scale&password=secret

有关可视化容器活动的更多详细信息,请查看调试部分。

☝️ 当对包含浏览器的镜像执行 docker run 命令时,请使用标志 --shm-size=2g 来使用主机的共享内存。

☝️ 始终使用带有完整标签的 Docker 镜像来固定特定的浏览器和 Grid 版本。有关详细信息,请参阅标签约定

在即用型 GitPod 环境中试用!

在 Gitpod 中打开


实验性多架构 amd64/aarch64/armhf 镜像

从基于 4.21.0 的镜像标签开始,本项目支持的架构如下:

架构 是否可用
x86_64(又称 amd64)
aarch64(又称 arm64/armv8)
armhf(又称 arm32/armv7l)

多架构浏览器镜像

以下浏览器在多架构镜像中可用:

架构 Chrome Chromium Firefox Edge CfT
x86_64(又称 amd64)
aarch64(又称 arm64/armv8)
armhf(又称 arm32/armv7l)

注意:

  • 不建议在 ARM64 平台上通过模拟运行 AMD64 镜像,因为这会导致性能和稳定性问题,或者浏览器可能无法启动。

  • Google Chrome(google-chrome)从 v150+ 开始,可通过 APT 稳定通道用于 Linux/ARM64。Chrome(节点和独立版)镜像支持多架构。旧版 Chrome 仍仅支持 AMD64;每个版本支持的平台通过 CHROME_PLATFORMS 键在浏览器矩阵中跟踪。 Microsoft 不为 Linux/ARM 平台构建 Edge(microsoft-edge),因此 Edge(节点和独立版)镜像仅适用于 AMD64。

  • Google 未发布适用于 Linux/ARM64 的 ChromeDriver 构建版本(Chrome for Testing 仅提供 linux64)。在 ARM64 上,Chrome 镜像使用相同主版本的 Chromium 驱动程序,该驱动程序取自 Debian chromium-driver 包,存档于 NDViet/chromium-stable。这些包遵循稳定通道,因此 Chrome devbeta 镜像仅适用于 AMD64。

  • 我们还提供 Chrome for Testing(CfT),但它仅适用于 Linux/AMD64。

  • 对于较旧的 Linux/ARM 系统,您也可以使用开源的 Chromium 浏览器。Chromium(节点和独立版)镜像支持多架构。

$ docker run --rm -it -p 4444:4444 -p 5900:5900 -p 7900:7900 --shm-size 2g selenium/standalone-chromium:latest
  • Mozilla Firefox 从 v136+ 版本开始,可通过 APT 稳定通道在 Linux/ARM64 上使用。Firefox(节点和独立版)镜像支持多架构。

多架构镜像已在 CircleCI 上使用 Linux/ARM64 资源类进行测试。状态如下。(已迁移至 GitHub Actions)

CircleCI

多架构镜像的历史

对于可在 Apple M 系列或树莓派等平台上运行的实验性 docker 容器镜像,seleniumhq-community/docker-seleniarm 仓库提供了相关镜像,这些镜像发布在 Seleniarm Docker Hub registry 上。

有关这些镜像的更多信息,请参见 issue #1076

现在,分支 seleniumhq-community/docker-seleniarm 已被合并。

本地构建多架构镜像

我们建议在 Docker Engine 中启用实验性功能 containerd 镜像存储containerd 支持多平台镜像,单个镜像标签可指向涵盖多种操作系统和硬件架构的不同变体。它简化了跨不同平台构建、存储和分发镜像的流程。

在 Docker Engine 中启用该功能的单行命令:

make set_containerd_image_store

注意:该命令仅与 Ubuntu 兼容。对于在 macOS 上使用 Docker Desktop 的用户,可以通过以下方式轻松启用

设置 > 通用 > 使用 containerd 拉取和存储镜像

要一次性为多平台构建所有镜像,请运行以下命令:

PLATFORMS=linux/amd64,linux/arm64 make all

要为特定平台构建镜像,请运行以下命令:

PLATFORMS=linux/arm64 make all

默认情况下,如果未指定 PLATFORMS 变量,镜像将使用当前主机架构进行构建。

同样,如果您使用的是主机 ARM64 架构,可以通过运行以下命令为 AMD64 架构构建镜像:

PLATFORMS=linux/amd64 make all

夜间构建镜像

夜间构建镜像是基于上游项目 SeleniumNightly 构建版本,并结合了本仓库主分支的最新变更构建而成。镜像标签为 nightly。不建议在生产环境中使用这些镜像,它们仅用于测试目的。

$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:nightly

查看 Docker Compose 以开始使用 Nightly 镜像 docker-compose-v3-full-grid-nightly.yml

开发版和测试版浏览器镜像

为了运行测试或使用预发布版本的浏览器,Google、Mozilla 和 Microsoft 均维护着开发版(Dev)和测试版(Beta)发布渠道,供需要了解即将向普通用户发布内容的人员使用。

开发版和测试版独立模式

以下是在独立模式下运行它们的说明:

Chrome Beta:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:beta

Chrome 开发版:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome:dev

Firefox Beta:

$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:beta

Firefox 开发者版:

$ docker run --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-firefox:dev

Edge Beta:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:beta

Edge Dev:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-edge:dev

测试版 Chrome for Testing:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome-for-testing:beta

测试版 Chrome Dev:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome-for-testing:dev

Chrome for Testing Canary:

$ docker run --platform linux/amd64 --rm -it -p 4444:4444 -p 7900:7900 --shm-size 2g selenium/standalone-chrome-for-testing:canary

网格上的开发版和测试版

docker-compose-v3-beta-channel.yml:

# To execute this docker compose yml file use `docker compose -f docker-compose-v3-beta-channel.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker compose -f docker-compose-v3-beta-channel.yml down`
services:
  chrome:
    image: selenium/node-chrome:beta
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  edge:
    image: selenium/node-edge:beta
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  firefox:
    image: selenium/node-firefox:beta
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  chrome-for-testing:
    image: selenium/node-chrome-for-testing:beta
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  selenium-hub:
    image: selenium/hub:latest
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

docker-compose-v3-dev-channel.yml:

# To execute this docker compose yml file use `docker compose -f docker-compose-v3-dev-channel.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker compose -f docker-compose-v3-dev-channel.yml down`
services:
  chrome:
    image: selenium/node-chrome:dev
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  edge:
    image: selenium/node-edge:dev
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  firefox:
    image: selenium/node-firefox:dev
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  chrome-for-testing:
    image: selenium/node-chrome-for-testing:dev
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub

  selenium-hub:
    image: selenium/hub:latest
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

有关开发版和测试版通道容器镜像的更多信息,请参阅博客文章 Dev and Beta Channel Browsers via Docker Selenium

包含所有浏览器的单节点/独立版镜像

从镜像标签 4.35.0 开始,提供了一个预安装所有浏览器的单节点/独立版镜像。这些镜像包括 selenium/standalone-all-browsers(独立全能版)和 selenium/node-all-browsers(适用于 Hub-Node 模式)。

这两个镜像适合以下用户:

  • 倾向于使用包含 Selenium Grid 和主流浏览器的“一体化”单一容器。
  • 不介意镜像大小,更看重使用便利性。
  • 工作负载较轻,能够自行评估资源消耗情况。

根据多架构支持,selenium/node-all-browsersselenium/standalone-all-browsers 镜像中提供的浏览器会因架构而异。

浏览器 / 架构 x86_64(又称 amd64) aarch64(又称 arm64/armv8)
Chrome
Edge
Firefox
Chromium

linux/amd64 架构的镜像中,Chrome 和 Chromium 浏览器二进制文件均可用。不过,默认激活的是 Chrome 浏览器二进制文件。如果需要切换到 Chromium 浏览器二进制文件,可以设置环境变量 SE_BROWSER_BINARY_LOCATION_CHROME=/usr/bin/chromium

通过环境变量 SE_NODE_ENABLE_BROWSER_<BROWSER>(其中 <BROWSER> 为大写的浏览器名称,例如 CHROMEFIREFOXEDGE),您可以在包含所有浏览器的节点/独立版镜像中禁用某个浏览器。

例如,对于 linux/amd64 和 linux/arm64 镜像,可以通过设置环境变量 SE_NODE_ENABLE_BROWSER_FIREFOX=false 来禁用 Firefox 浏览器。

例如,对于 linux/amd64 镜像,可以通过设置环境变量 SE_NODE_ENABLE_BROWSER_CHROME=false 来禁用 Chrome 浏览器。禁用 Edge 浏览器的方法类似,设置 SE_NODE_ENABLE_BROWSER_EDGE=false 即可。

以下是在包含所有浏览器的节点/独立版镜像中支持后缀 _<BROWSER> 的环境变量列表:

SE_NODE_STEREOTYPE
SE_NODE_BROWSER_NAME
SE_NODE_BROWSER_VERSION
SE_NODE_PLATFORM_NAME
SE_BROWSER_BINARY_LOCATION
SE_NODE_STEREOTYPE_EXTRA
SE_NODE_MAX_SESSIONS

环境变量

完整环境变量列表请查看此处

如何更新或参与环境变量列表的贡献?请按照以下步骤操作:

  1. 刷新列表以获取新增的环境变量或默认值

    make update_list_env_vars
    

    可在scripts/generate_list_env_vars/extract_env.py中更新该脚本。

  2. 在文件scripts/generate_list_env_vars/description.yaml中更新每个环境变量的描述。

  3. 再次运行步骤(1)中的命令,以使用新描述更新环境变量列表。

执行模式

独立模式

Firefox

Firefox

docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-firefox:4.47.0-20260808

Chrome

Chrome

docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.47.0-20260808

Edge

Edge

docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-edge:4.47.0-20260808

单个容器中的所有浏览器

docker run -d -p 4444:4444 --shm-size="3g" selenium/standalone-all-browsers:4.47.0-20260808

注意:同一时间只能有一个 Standalone 容器在端口 4444 上运行。


中心节点与工作节点

有多种方式可以运行镜像并创建包含中心节点(Hub)和工作节点(Nodes)的网格(Grid),请查看以下选项。

Docker 网络

中心节点和工作节点将创建在同一网络中,它们可以通过容器名称相互识别。 第一步需要创建一个 Docker 网络

macOS/Linux

中心节点和多个浏览器工作节点容器

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-chrome:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-edge:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-firefox:4.47.0-20260808

包含所有浏览器的 Hub 和单个 Node 容器

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="3g" \
    selenium/node-all-browsers:4.47.0-20260808
Windows PowerShell

中心节点和多个浏览器节点容器

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
    --shm-size="2g" `
    selenium/node-chrome:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
    --shm-size="2g" `
    selenium/node-edge:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
    --shm-size="2g" `
    selenium/node-firefox:4.47.0-20260808

包含所有浏览器的 Hub 和单 Node 容器

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
    --shm-size="3g" `
    selenium/node-all-browsers:4.47.0-20260808

当您使用完 Grid 且容器已退出后,可通过以下命令移除网络:

# Removes the grid network
$ docker network rm grid

使用不同的机器/VM

Hub 和 Node 将在不同的机器/VM 上创建,它们需要知道彼此的 IP 才能正常通信。如果同一台机器/VM 上要运行多个 Node,则必须将它们配置为暴露不同的端口。

Hub - 机器/VM 1
$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.47.0-20260808
Node Chrome - 机器/虚拟机 2
macOS/Linux
$ docker run -d -p 5555:5555 \
    --shm-size="2g" \
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> \
    -e SE_NODE_HOST=<ip-from-machine-2> \
    selenium/node-chrome:4.47.0-20260808
Windows PowerShell
$ docker run -d -p 5555:5555 `
    --shm-size="2g" `
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
    -e SE_NODE_HOST=<ip-from-machine-2> `
    selenium/node-chrome:4.47.0-20260808
节点 Edge - 机器/虚拟机 3
macOS/Linux
$ docker run -d -p 5555:5555 \
    --shm-size="2g" \
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> \
    -e SE_NODE_HOST=<ip-from-machine-3> \
    selenium/node-edge:4.47.0-20260808
Windows PowerShell
$ docker run -d -p 5555:5555 `
    --shm-size="2g" `
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
    -e SE_NODE_HOST=<ip-from-machine-3> `
    selenium/node-edge:4.47.0-20260808
Node Firefox - 机器/虚拟机 4
macOS/Linux
$ docker run -d -p 5555:5555 \
    --shm-size="2g" \
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> \
    -e SE_NODE_HOST=<ip-from-machine-4> \
    selenium/node-firefox:4.47.0-20260808
Windows PowerShell
$ docker run -d -p 5555:5555 `
    --shm-size="2g" `
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
    -e SE_NODE_HOST=<ip-from-machine-4> `
    selenium/node-firefox:4.47.0-20260808
节点 Chrome - 机器/虚拟机 4
macOS/Linux
$ docker run -d -p 5556:5556 \
    --shm-size="2g" \
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> \
    -e SE_NODE_HOST=<ip-from-machine-4> \
    -e SE_NODE_PORT=5556 \
    selenium/node-chrome:4.47.0-20260808
Windows PowerShell
$ docker run -d -p 5556:5556 `
    --shm-size="2g" `
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
    -e SE_NODE_HOST=<ip-from-machine-4> `
    -e SE_NODE_PORT=5556 `
    selenium/node-chrome:4.47.0-20260808

Docker Compose

Docker Compose 是启动 Grid 最简单的方式。使用下面链接的资源,将它们保存到本地,并查看每个文件顶部的执行说明。

版本 2

docker-compose-v2.yml

版本 3

docker-compose-v3.yml

要停止 Grid 并清理创建的容器,请运行 docker compose down

支持 Swarm 的版本 3

docker-compose-v3-swarm.yml


完全分布式模式 - 路由器、队列、分发器、事件总线、会话映射和节点

可以将 Selenium Grid 的所有组件分开启动。为简单起见,仅提供一个使用 docker compose 的示例。将文件保存到本地,并查看其顶部的执行说明。

docker-compose-v3-full-grid.yml

分发器配置

环境变量 选项 类型 默认值 描述
SE_REJECT_UNSUPPORTED_CAPS --reject-unsupported-caps boolean false 允许分发器在 Grid 不支持请求的功能时立即拒绝请求。
SE_HEALTHCHECK_INTERVAL --healthcheck-interval int 120 确保服务器能在指定间隔后成功 ping 所有节点。
SE_DISTRIBUTOR_SLOT_SELECTOR --slot-selector string `` 非默认插槽选择器的完整类名。用于在匹配到节点后选择该节点中的插槽。

分发器组件内置了两种主要的插槽选择器实现:

  • org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector:Grid 的默认策略(如果未配置其他选择器,则使用此策略)。它遵循上述的平衡、最近最少使用方法。DefaultSlotSelector 会选择空闲时间最长的节点,确保在其他节点空闲时不会过度使用单个节点。这种简单策略开销极小,适用于大多数需要均匀分配会话的常规测试场景。

  • org.openqa.selenium.grid.distributor.selector.GreedySlotSelector:提供的另一种内置选择器。GreedySlotSelector 旨在通过在使用另一个节点之前集中将会话分配到一个节点来最大化节点利用率。如前所述,它会倾向于逐个填满一个节点的插槽,减少任何时候部分利用的节点数量。此策略适用于资源密集型或高并发场景(例如,负载测试或在按需扩展节点的环境中运行)。更多信息,请参考 #2990


视频录制

可以通过使用 selenium/video:ffmpeg-8.1-20260808 Docker 镜像来录制测试执行过程。每个运行浏览器的容器都需要对应一个视频容器。这意味着如果您运行 5 个节点/独立容器,就需要 5 个视频容器,映射关系为 1:1。

目前,实现这种映射的唯一方式是手动操作(要么手动启动容器,要么通过 docker compose)。我们正在对这一流程进行优化,未来这种设置可能会更加简单。

我们提供的视频 Docker 镜像是基于 jrottenberg/ffmpeg 项目提供的 ffmpeg Ubuntu 镜像构建的,感谢该项目提供此镜像,简化了我们的工作 🎉

4.20.0 及后续版本的镜像标签开始,视频 Docker 镜像基于 linuxserver/docker-ffmpeg 项目提供的 FFmpeg Ubuntu 镜像构建,因为该镜像支持多平台。感谢该项目为我们的项目提供了便利,并帮助我们实现了多架构支持。

注意事项

  • 如有疑问或反馈,请使用 此处 所示的社区联系方式。
  • 请通过 GitHub issues 报告任何错误,并提供模板中要求的所有信息。
  • 不支持无头浏览器的视频录制。
  • 视频录制往往会占用大量 CPU。通常,您应估计每个视频容器需要 1 个 CPU,每个浏览器容器也需要 1 个 CPU。
  • 视频存储在视频容器内的 /videos 目录中。请映射一个本地目录以获取视频。
  • 如果您运行多个视频容器,请务必通过 FILE_NAME 环境变量覆盖视频文件名,以避免意外结果。

以下示例展示了如何手动启动容器:

$ docker network create grid
$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium --shm-size="2g" selenium/standalone-chrome:4.47.0-20260808
$ docker run -d --net grid --name video -v /tmp/videos:/videos selenium/video:ffmpeg-8.1-20260808
# Run your tests
$ docker stop video && docker rm video
$ docker stop selenium && docker rm selenium

容器停止并移除后,您应该会在本地机器的 /tmp/videos 目录中看到一个视频文件。

以下是使用 Hub 和几个 Node 的示例:

docker-compose-v3-video.yml

基于测试元数据的动态视频文件名录制

基于 测试中的元数据 支持。当视频录制器作为 sidecar 与浏览器节点一起部署,并启用 SE_VIDEO_FILE_NAME=auto 且在测试中添加元数据时,视频文件名会提取 se:name 功能的值并将其用作视频文件名。

例如在 Python 绑定中:

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver

options = ChromeOptions()
options.set_capability('se:name', 'test_visit_basic_auth_secured_page (ChromeTests)')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")
driver.get("https://selenium.dev")
driver.quit()

输出视频文件的名称将为 test_visit_basic_auth_secured_page_ChromeTests_<sessionId>.mp4

如果测试名称由测试框架处理,并且确保是唯一的,你还可以通过设置 SE_VIDEO_FILE_NAME_SUFFIX=false 来禁用在视频文件名后附加会话 ID。

文件名会被截断为 255 个字符,以避免过长的文件名。此外,space 字符会被替换为 _,并且文件名中仅保留字母、数字、-(连字符)、_(下划线)。

可以通过设置 SE_VIDEO_FILE_NAME_TRIM_REGEX 环境变量来自定义截断正则表达式。默认值为 [^a-zA-Z0-9-_]。该正则表达式应与 Python re.compile() 函数兼容。

在部署层面,录制器容器始终处于启动状态并待命,监控会话。是否录制特定会话由 se:recordVideo 功能按会话控制,该功能会覆盖 SE_RECORD_VIDEO 环境变量(当该功能不存在时,SE_RECORD_VIDEO 用作默认值):

  • 会话中存在 se:recordVideo 功能:其值决定该会话是否录制(true 表示录制,false 表示跳过),与 SE_RECORD_VIDEO 无关。
  • 会话中不存在 se:recordVideo 功能:录制器回退到 SE_RECORD_VIDEO(独立视频镜像的默认值为 true,节点镜像的默认值为 false)。

这意味着你可以默认禁用录制,并按测试选择性启用。例如,设置 SE_VIDEO_FILE_NAME_SUFFIX=false 后,录制器将保持待命状态,仅录制明确请求录制的会话:

# Recorded only because the session opts in, even when SE_RECORD_VIDEO=false
options.set_capability('se:recordVideo', True)

相反,如果默认启用了录制功能(SE_RECORD_VIDEO=true),你可以为特定会话禁用它:

options.set_capability('se:recordVideo', False)

此每会话控制适用于两种录制模式:

  • 事件驱动模式SE_VIDEO_EVENT_DRIVEN=true,Node 镜像中的默认模式):录制器订阅 Grid 事件总线,并在 SessionCreated 事件中从每个会话的功能中读取 se:recordVideo
  • Shell/轮询模式SE_VIDEO_EVENT_DRIVEN=false):录制器根据 Node SessionId 查询 Node 的 /status 端点(或 Hub GraphQL 端点),并从功能中提取 se:recordVideo,然后决定是否开始录制。

注意:要使 shell/轮询模式能够访问 GraphQL 端点,录制器容器需要知道 Hub URL。可以通过环境变量 SE_NODE_GRID_URL 传递 Hub URL。例如,SE_NODE_GRID_URL 可以设为 http://selenium-hub:4444

视频录制和上传

视频录制器镜像中已安装 RCLONE。您可以使用它将视频上传到云存储服务。 除了上述视频录制功能外,您可以通过设置以下环境变量来启用上传功能:

services:
  chrome_video:
    image: selenium/video:ffmpeg-8.1-20260808
    depends_on:
      - chrome
    environment:
      - DISPLAY_CONTAINER_NAME=chrome
      - SE_VIDEO_FILE_NAME=auto
      - SE_VIDEO_UPLOAD_ENABLED=true
      - SE_UPLOAD_DESTINATION_PREFIX=s3://mybucket/path
      - RCLONE_CONFIG_S3_TYPE=s3
      - RCLONE_CONFIG_S3_PROVIDER=GCS
      - RCLONE_CONFIG_S3_ENV_AUTH=true
      - RCLONE_CONFIG_S3_REGION=asia-southeast1
      - RCLONE_CONFIG_S3_LOCATION_CONSTRAINT=asia-southeast1
      - RCLONE_CONFIG_S3_ACL=private
      - RCLONE_CONFIG_S3_ACCESS_KEY_ID=xxx
      - RCLONE_CONFIG_S3_SECRET_ACCESS_KEY=xxx
      - RCLONE_CONFIG_S3_ENDPOINT=https://storage.googleapis.com
      - RCLONE_CONFIG_S3_NO_CHECK_BUCKET=true

SE_VIDEO_FILE_NAME=auto 会将会话 ID 用作视频文件名。这样可以确保视频文件名具有唯一性,便于上传。

视频文件名的构建会自动基于节点端点 /status(以及可选的 GraphQL 端点)来获取会话 ID 和功能。

SE_VIDEO_UPLOAD_ENABLED=true 会在传统的基于 shell 的模式(SE_VIDEO_EVENT_DRIVEN=false)下启用上传功能。在事件驱动模式(默认模式)下,此变量已弃用——当 SE_UPLOAD_DESTINATION_PREFIX 设置为非空值时,上传功能会自动启用。

SE_VIDEO_INTERNAL_UPLOAD=true(默认值)将使用容器中安装的 RCLONE 进行上传。如果希望使用其他 sidecar 容器进行上传,请将其设置为 false

各模式下的环境变量 中心节点/节点 独立角色 动态网格
SE_VIDEO_RECORD_STANDALONE(必填) false(默认) true true
DISPLAY_CONTAINER_NAME(必填) 用户输入 用户输入 (不需要)
SE_NODE_PORT(可选) 5555 4444 (不需要)
SE_NODE_GRID_URL(可选) 用户输入 (不需要) (不需要)

前缀为 RCLONE_ 的环境变量用于向 RCLONE 传递远程配置。你可以在此处找到有关 RCLONE 配置的更多信息。 在动态网格中使用时,这些变量应与前缀 SE_ 组合使用,例如 SE_RCLONE_。更多详细信息请参见下面的参考资料。

参考资料

上传功能的环境变量及默认值

环境变量 默认值 描述
SE_UPLOAD_RETAIN_LOCAL_FILE false 成功上传后保留本地文件
SE_UPLOAD_COMMAND copy 用于传输文件的 RCLONE 命令。当保留本地文件设为 false 时强制使用 move
SE_UPLOAD_OPTS -P --cutoff-mode SOFT --metadata --inplace 可设置 RCLONE 命令的其他选项。
SE_UPLOAD_CONFIG_FILE_NAME upload.conf 远程主机的配置文件,替代通过 SE_RCLONE_* 前缀的环境变量进行设置
SE_UPLOAD_CONFIG_DIRECTORY /opt/bin 配置文件的目录(当挂载其他目录中的配置文件时需修改此值)

仅保留失败会话的录制文件

在事件驱动模式下(SE_VIDEO_EVENT_DRIVEN=true,默认设置),视频服务会订阅 Grid 的 ZeroMQ 事件总线,并实时响应会话生命周期事件。这支持一种失败时保留策略:录制每个会话,但当会话成功时自动丢弃视频,仅保留(并上传)失败会话的录制文件。

通过以下环境变量全局启用此功能:

SE_RETAIN_ON_FAILURE=true

当满足以下任一条件时,会话将被视为失败

  1. 测试代码触发的会话事件中,其 eventType 包含 SE_FAILURE_SESSION_EVENTS 中的某个子字符串(默认值::failed,:failure,:error,:aborted)。
  2. 会话以异常原因关闭,包括 TIMEOUTNODE_REMOVEDNODE_RESTARTED,而非正常的 QUIT_COMMAND
环境变量 默认值 描述
SE_RETAIN_ON_FAILURE false 丢弃通过会话的录制。仅将失败会话的录制保留在磁盘上并排队等待上传。
SE_FAILURE_SESSION_EVENTS :failed,:failure,:error,:aborted 逗号分隔的子字符串。任何 eventType 包含其中任一子字符串(不区分大小写)的会话事件,都会将该会话标记为失败。

会话功能 se:retainOnFailure 会覆盖特定会话的全局容器环境变量。例如,要忽略全局设置而保留单个会话的录制:

options.set_capability('se:retainOnFailure', True)
se:retainOnFailure 功能 SE_RETAIN_ON_FAILURE 环境变量 实际行为
true false(默认) 针对此会话,失败时保留
false true 针对此会话,始终保留
不存在 true 失败时保留(全局默认)
不存在 false(默认) 始终保留(全局默认)

从测试代码触发会话事件

会话事件 API 允许测试代码将命名事件直接推送到 Grid。视频服务通过 ZeroMQ 总线监听这些事件,并据此判断会话是否失败。

在测试中调用 driver.fire_session_event(eventType, payload)。任何包含已配置失败子字符串的 eventType(例如,"test:failed" 包含 ":failed")都会将会话标记为失败。

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver

options = ChromeOptions()
options.set_capability('se:name', 'checkout_flow')
options.set_capability('se:retainOnFailure', True)   # discard video if this session passes

driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")

try:
    driver.get("https://selenium.dev")
    # ... test steps ...
except Exception as exc:
    # "test:failed" contains ":failed" — matches the default SE_FAILURE_SESSION_EVENTS
    driver.fire_session_event("test:failed", {"error": str(exc)})
    raise
finally:
    driver.quit()

注意: 如果测试捕获到异常但仍正常调用 driver.quit(),会话关闭原因将是 QUIT_COMMAND(非异常)。在这种情况下, quit() 之前触发失败事件是将会话标记为失败并防止录制被丢弃的唯一方法。

因此,您可以通过会话功能和触发会话事件,从测试代码中完全控制 失败时保留 策略。

视频录制管理器

我们使用 File Browser 作为视频管理器。它是一个基于 Web 的文件管理器,允许您管理存储中的文件和文件夹。

File Browser 容器的 /srv 目录应挂载到与存储视频录制相同的存储位置。例如,一个 compose 文件:

services:
  chrome:
    deploy:
      mode: replicated
      replicas: 3
    image: selenium/node-chrome:4.47.0-20260808
    platform: linux/amd64
    shm_size: 2gb
    depends_on:
      - selenium-hub
    volumes:
      - /tmp/videos:/videos
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_RECORD_VIDEO=true
      - SE_VIDEO_FILE_NAME=auto
      - SE_NODE_GRID_URL=http://selenium-hub:4444

  file_browser:
      image: filebrowser/filebrowser:latest
      container_name: file_browser
      restart: always
      ports:
          - "8081:80"
      volumes:
          - /tmp/videos:/srv
      environment:
          - FB_NOAUTH=true

动态网格

Grid 4 具备按需启动 Docker 容器的能力,这意味着它会为每个新的会话请求在后台启动一个 Docker 容器,测试在该容器中执行,测试完成后,容器即被销毁。

此执行模式可用于独立(Standalone)角色或节点(Node)角色。“动态”执行模式需要指定启动容器时要使用的 Docker 镜像。此外,网格需要知道 Docker 守护进程的 URI。这些配置可放置在本地的 toml 文件中。

配置示例

您可以在本地保存此文件,并将其命名为(例如)config.toml

[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
    "selenium/standalone-firefox:4.47.0-20260808", '{"browserName": "firefox"}',
    "selenium/standalone-chrome:4.47.0-20260808", '{"browserName": "chrome"}',
    "selenium/standalone-edge:4.47.0-20260808", '{"browserName": "MicrosoftEdge"}'
]

host-config-keys = ["Dns", "DnsOptions", "DnsSearch", "ExtraHosts", "Binds"]

# URL for connecting to the docker daemon
# Most simple approach, leave it as http://127.0.0.1:2375, and mount /var/run/docker.sock.
# 127.0.0.1 is used because internally the container uses socat when /var/run/docker.sock is mounted 
# If var/run/docker.sock is not mounted: 
# Windows: make sure Docker Desktop exposes the daemon via tcp, and use http://host.docker.internal:2375.
# macOS: install socat and run the following command, socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock,
# then use http://host.docker.internal:2375.
# Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue.
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-8.1-20260808"

# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appropriate values
#[server]
#host = <ip-from-node-machine>
#port = <port-from-node-machine>

将本地 config.toml 文件挂载到容器路径 /opt/selenium/docker.toml。 此配置文件路径默认专用于动态网格(节点/独立 docker),以避免与节点浏览器容器中的配置文件冲突(因为用户可以将卷配置共享给节点浏览器容器,详情见下文部分)。

通过 config.toml 文件中 [docker] 部分下的可选配置键 host-config-keys(或 CLI 选项 --docker-host-config-keys),用户可以指定应传递给浏览器容器的 docker 主机配置键列表。

Docker 主机配置的有效键名可在 Docker API 文档 中找到,或通过 docker inspect 命令查看 node-docker 容器获取。

将动态网格容器的卷配置共享给节点浏览器容器

如果您希望通过动态网格容器的卷配置访问节点浏览器容器中的下载目录(例如 /home/seluser/Downloads),可以将以下配置添加到 config.toml 文件中

[docker]
host-config-keys = ["Binds"]

docker compose 文件中的卷配置

services:
  node-docker:
    image: selenium/node-docker:latest
    volumes:
      - ./assets:/opt/selenium/assets
      - ./config.toml:/opt/selenium/docker.toml
      - ./downloads:/home/seluser/Downloads
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - SE_NODE_DOCKER_CONFIG_FILENAME=docker.toml

/opt/selenium/config.toml 是所有镜像中配置文件的默认路径。一旦将卷配置共享给节点浏览器容器,其 config.toml 可能会被节点 Docker 容器的配置文件覆盖。

在这种情况下,请将您的 config.toml 文件挂载到节点 Docker 容器的 /opt/selenium/docker.toml 路径。并设置环境变量 SE_NODE_DOCKER_CONFIG_FILENAME=docker.toml,以指定启动脚本使用的配置文件名。

参考示例 docker-compose-v3-test-node-docker.yaml

使用 Hub 和 Node 角色执行

这可以扩展为完整的 Grid 部署,所有组件单独部署。总体思路是将 Hub 部署在一台虚拟机上,而每个 Node 部署在单独且性能更强的虚拟机上。

macOS/Linux

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    -v ${PWD}/config.toml:/opt/selenium/docker.toml \
    -v ${PWD}/assets:/opt/selenium/assets \
    -v /var/run/docker.sock:/var/run/docker.sock \
    selenium/node-docker:4.47.0-20260808

Windows PowerShell

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub `
    -v ${PWD}/config.toml:/opt/selenium/docker.toml `
    -v ${PWD}/assets:/opt/selenium/assets `
    -v /var/run/docker.sock:/var/run/docker.sock `
    selenium/node-docker:4.47.0-20260808

若要将资源保存到主机上,请将主机路径挂载到 /opt/selenium/assets

当您使用完 Grid 且容器已退出后,可通过以下命令移除网络:

# Removes the grid network
$ docker network rm grid

独立角色执行

macOS/Linux

docker run --rm --name selenium-docker -p 4444:4444 \
    -v ${PWD}/config.toml:/opt/selenium/docker.toml \
    -v ${PWD}/assets:/opt/selenium/assets \
    -v /var/run/docker.sock:/var/run/docker.sock \
    selenium/standalone-docker:4.47.0-20260808

Windows PowerShell

docker run --rm --name selenium-docker -p 4444:4444 `
    -v ${PWD}/config.toml:/opt/selenium/docker.toml `
    -v ${PWD}/assets:/opt/selenium/assets `
    -v /var/run/docker.sock:/var/run/docker.sock `
    selenium/standalone-docker:4.47.0-20260808

在不同机器/虚拟机中使用动态网格

中心节点 - 机器/虚拟机 1

$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.47.0-20260808

Node Chrome - 机器/虚拟机 2

macOS/ Linux

$ docker run -d -p 5555:5555 \
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> \
    -v ${PWD}/config.toml:/opt/selenium/docker.toml \
    -v ${PWD}/assets:/opt/selenium/assets \
    -v /var/run/docker.sock:/var/run/docker.sock \
    selenium/node-docker:4.47.0-20260808

Windows PowerShell

$ docker run -d -p 5555:5555 `
    -e SE_EVENT_BUS_HOST=<ip-from-machine-1> `
    -v ${PWD}/config.toml:/opt/selenium/docker.toml `
    -v ${PWD}/assets:/opt/selenium/assets `
    -v /var/run/docker.sock:/var/run/docker.sock `
    selenium/node-docker:4.47.0-20260808

完成 config.toml 文件中的 [server] 部分。

[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
    "selenium/standalone-firefox:4.47.0-20260808", "{\"browserName\": \"firefox\"}",
    "selenium/standalone-chrome:4.47.0-20260808", "{\"browserName\": \"chrome\"}",
    "selenium/standalone-edge:4.47.0-20260808", "{\"browserName\": \"MicrosoftEdge\"}"
    ]

# URL for connecting to the docker daemon
# Most simple approach, leave it as http://127.0.0.1:2375, and mount /var/run/docker.sock.
# 127.0.0.1 is used because interally the container uses socat when /var/run/docker.sock is mounted 
# If var/run/docker.sock is not mounted: 
# Windows: make sure Docker Desktop exposes the daemon via tcp, and use http://host.docker.internal:2375.
# macOS: install socat and run the following command, socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock,
# then use http://host.docker.internal:2375.
# Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue.
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-8.1-20260808"

# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appropriate values
[server]
host = <ip-from-node-machine>
port = <port-from-node-machine>

若要将资源保存到主机,请将主机路径挂载到 /opt/selenium/assets

使用 Docker Compose 执行

以下是使用 Hub 和 Node 的示例:

docker-compose-v3-dynamic-grid.yml

配置子容器

可以通过环境变量进一步配置容器,例如 SE_NODE_SESSION_TIMEOUTSE_OPTS。创建子容器时,所有以 SE_ 为前缀的环境变量都会被转发并设置到容器中。您可以在 standalone-dockernode-docker 容器中设置所需的环境变量。以下示例将所有会话的超时时间设置为 700 秒:

macOS/Linux

docker run --rm --name selenium-docker -p 4444:4444 \
    -e SE_NODE_SESSION_TIMEOUT=700 \
    -v ${PWD}/config.toml:/opt/selenium/docker.toml \
    -v ${PWD}/assets:/opt/selenium/assets \
    -v /var/run/docker.sock:/var/run/docker.sock \
    selenium/standalone-docker:4.47.0-20260808

Windows PowerShell

docker run --rm --name selenium-docker -p 4444:4444 `
    -e SE_NODE_SESSION_TIMEOUT=700 `
    -v ${PWD}/config.toml:/opt/selenium/docker.toml `
    -v ${PWD}/assets:/opt/selenium/assets `
    -v /var/run/docker.sock:/var/run/docker.sock `
    selenium/standalone-docker:4.47.0-20260808

动态网格中的视频录制、屏幕分辨率和时区设置

若要录制 WebDriver 会话,您需要添加一个设为 truese:recordVideo 字段。您还可以设置时区和屏幕分辨率,例如:

{
  "browserName": "firefox",
  "platformName": "linux",
  "se:recordVideo": "true",
  "se:timeZone": "US/Pacific",
  "se:screenResolution": "1920x1080"  
}

运行测试后,请检查您挂载到 Docker 容器的路径(${PWD}/assets),您应该会看到视频和会话信息。

您可以通过语言绑定设置 se:name 功能,动态更改输出视频文件的名称。例如,在 Python 绑定中:

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium import webdriver

options = ChromeOptions()
options.set_capability('se:recordVideo', True)
options.set_capability('se:screenResolution', '1920x1080')
options.set_capability('se:name', 'test_visit_basic_auth_secured_page (ChromeTests)')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444")
driver.get("https://selenium.dev")
driver.quit()

测试执行后,在 ${PWD}/assets 目录下,您可以在路径 /<sessionId>/test_visit_basic_auth_secured_page_ChromeTests.mp4 中看到视频文件名称。

文件名将被截断为 255 个字符,以避免长文件名。此外,空格字符将被替换为下划线(_),并且文件名中仅保留字母、数字、连字符(-)和下划线(_)。(此功能在 PR 合并后可用)

通过环境变量配置时区

基础镜像中已安装 tzdata,您可以使用环境变量 TZ 来设置容器中的时区。 默认情况下,时区设置为 UTC。 支持的时区列表可在 此处 找到。例如:

$ docker run --rm --entrypoint="" -e TZ=Asia/Ho_Chi_Minh selenium/node-chromium:latest date +%FT%T%Z
2024-08-28T18:19:26+07

部署到 Kubernetes

开始在 Kubernetes 上部署 Selenium Grid,您可以参考 kubernetes 目录中的 YAML 文件。

为了简化部署流程、隐藏 Kubernetes 对象的复杂性,并提供一种更直接的方式在 Kubernetes 上部署 Selenium Grid,我们提供了一个 Helm chart 来将 Selenium Grid 部署到 Kubernetes。 有关更多详细信息,请参阅 Helm chart READMEchart CONFIGURATION

  • 开始动手在 Kubernetes 上使用 Selenium Grid。请参阅使用 Docker Desktop 进行本地环境设置。

配置容器

SE_OPTS Selenium 配置选项

您可以传递 SE_OPTS 变量以及用于启动 hub 或 node 的其他命令行参数。

$ docker run -d -p 4444:4444 -e SE_OPTS="--log-level FINE" --name selenium-hub selenium/hub:4.47.0-20260808

SE_JAVA_OPTS Java 环境选项

您可以将 SE_JAVA_OPTS 环境变量传递给 Java 进程。

$ docker run -d -p 4444:4444 -e SE_JAVA_OPTS=-Xmx512m --name selenium-hub selenium/hub:4.47.0-20260808

SE_BROWSER_ARGS_* 添加用于启动浏览器的参数

无需通过语言绑定中的浏览器选项添加参数,例如:

options = ChromeOptions()
options.add_argument('--incognito')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Remote(options=options, command_executor="http://localhost:4444/wd/hub")

您还可以主动从(node、standalone 或 node-docker)容器环境变量中直接强制应用参数。定义名称以 SE_BROWSER_ARGS_ 开头的环境变量,后面跟上您自定义的配置键(定义多个参数时确保这些键是唯一的)。例如:

docker run -d -p 4444:4444 \
  -e SE_BROWSER_ARGS_INCOGNITO=--incognito \
  -e SE_BROWSER_ARGS_DISABLE_DSHM=--disable-dev-shm-usage \
  selenium/standalone-chrome:latest

Chromium 命令行参数列表供您参考。

注意:目前,这适用于节点浏览器 Chrome/Chromium、Edge。

节点配置选项

节点通过事件总线(Event Bus)进行注册。当以典型的 Hub/Node 模式启动 Grid 时,Hub 将充当事件总线;而当 Grid 的五个组件分别独立启动时,事件总线将单独运行。

在这两种情况下,都需要告知节点事件总线的位置,以便节点能够注册自身。这就是 SE_EVENT_BUS_HOSTSE_EVENT_BUS_PUBLISH_PORTSE_EVENT_BUS_SUBSCRIBE_PORT 环境变量的作用。

在某些情况下,例如您想要为节点添加标签时,可能需要为节点配置提供自定义的刻板印象(stereotype)。环境变量 SE_NODE_STEREOTYPE 用于设置节点 config.toml 文件中的刻板印象条目。您可以在此处找到示例 config.toml 文件:为匹配特定节点设置自定义功能

以下是这些环境变量默认值的示例:

$ docker run -d \
  -e SE_EVENT_BUS_HOST=<event_bus_ip|event_bus_name> \
  -e SE_NODE_STEREOTYPE="{\"browserName\":\"${SE_NODE_BROWSER_NAME}\", \"browserVersion\":\"${SE_NODE_BROWSER_VERSION}\", \"platformName\":\"${SE_NODE_PLATFORM_NAME}\"}" \
  --shm-size="2g" selenium/node-chrome:4.47.0-20260808

在另一种情况下,如果您希望保留默认的 Node 模板并附加其他功能,可以使用 SE_NODE_STEREOTYPE_EXTRA 环境变量来设置您的功能。这些功能将合并到默认模板中。例如:

$ docker run -d \
  -e SE_EVENT_BUS_HOST=<event_bus_ip|event_bus_name> \
  -e SE_NODE_STEREOTYPE_EXTRA="{\"myApp:version\":\"beta\", \"myApp:publish:\":\"public\"}" \
  --shm-size="2g" selenium/node-chrome:4.47.0-20260808

这有助于设置自定义功能以匹配特定节点。例如,你在启动节点时添加了自定义功能,并且希望将测试分配到与你功能匹配的节点上运行。例如在测试代码中:

options = ChromeOptions()
options.set_capability('myApp:version', 'beta')
options.set_capability('myApp:publish', 'public')
driver = webdriver.Remote(options=options, command_executor=SELENIUM_GRID_URL)

注意:您的自定义功能及其键值必须遵循 W3C 功能约定,扩展功能的键必须包含“:”(冒号)字符,以表示特定于实现的命名空间。

注意:确保在 config.toml中将节点配置 detect-drivers = false(或在 CLI 选项中使用 --detect-drivers false),这样才能使设置自定义功能以匹配特定节点的特性正常工作。

此外,默认节点原型包含 se:containerName 功能,该功能可在节点功能或会话功能中查看,用于标识节点/会话运行所在的容器名称。带前缀的 se:containerName 不包含在槽匹配器中。默认情况下,其值取自容器内的 hostname 命令,该值等同于您通过 docker ps 命令看到的 container_id。如果您想覆盖此值,可以将环境变量 SE_NODE_CONTAINER_NAME 设置为您所需的值。例如,在部署到 Kubernetes 集群时,您可以将 Pod 名称分配给环境变量 SE_NODE_CONTAINER_NAME,以跟踪节点运行在哪个 Pod 中。

  env:
    - name: SE_NODE_CONTAINER_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name

在高级场景中,你可以控制启动一个 Node 容器,让它注册到 Hub,然后触发测试,使其恰好分配到该 Node 上运行。默认情况下,命令 $(hostname) 的值会添加到 Node 构造型的 container:hostname 功能名称中。结合上述为匹配特定 Node 设置自定义功能的特性,你可以使用刚启动的 Node 容器的 hostname 并将其设置为自定义功能。例如,在 Python 绑定中:

$ docker run -d --name my-node-1 -e SE_EVENT_BUS_HOST=localhost \
  --shm-size="2g" selenium/node-chrome:4.47.0-20260808
$ docker exec -i my-node-1 hostname
a6971f95bbab
options = ChromeOptions()
options.set_capability('container:hostname', 'a6971f95bbab')
driver = webdriver.Remote(options=options, command_executor=SELENIUM_GRID_URL)

注意:上述变更需要包含变更集并发布新的镜像标签。

节点配置中继命令

将命令中继到支持 WebDriver 的服务端点。 这对于将支持 WebDriver 的外部服务连接到 Selenium Grid 非常有用。此类服务的示例可以是云提供商或 Appium 服务器。 通过这种方式,Grid 可以扩展对本地未提供的平台和版本的覆盖范围。

以下是配置中继命令的示例。

docker-compose-v3-test-node-relay.yml

如果只需中继命令,selenium/node-base 是合适的轻量级选择。 如果要配置同时包含浏览器和中继命令的节点,可以使用相应的节点镜像。

要使用环境变量生成中继配置,请按如下方式设置 SE_NODE_RELAY_URL 和其他变量。这些变量将用于生成如下所示的默认 TOML 格式中继配置。

[relay]
url = "${SE_NODE_RELAY_URL}"
status-endpoint = "${SE_NODE_RELAY_STATUS_ENDPOINT}"
protocol-version = "${SE_NODE_RELAY_PROTOCOL_VERSION}"
configs = [ '${SE_NODE_RELAY_MAX_SESSIONS}', '{"browserName": "${SE_NODE_RELAY_BROWSER_NAME}", "platformName": "${SE_NODE_RELAY_PLATFORM_NAME}", "appium:platformVersion": "${SE_NODE_RELAY_PLATFORM_VERSION}"}' ]

无需为每个环境变量输入值来构建默认的中继构造型,您可以使用 SE_NODE_RELAY_STEREOTYPE 环境变量,用自定义构造型覆盖默认的中继构造型。

另一种情况,如果您希望保留默认的中继构造型并附加其他功能,可以使用 SE_NODE_RELAY_STEREOTYPE_EXTRA 环境变量来设置您的功能。这些功能将合并到默认的中继构造型中。

要使用中继节点运行示例测试,您可以克隆项目并尝试以下命令:

make test_node_relay

设置子路径

默认情况下,Selenium 可通过 http://127.0.0.1:4444/ 访问。通过指定 SE_SUB_PATH 环境变量,可以将 Selenium 配置为使用自定义子路径。在下面的示例中,Selenium 可通过 http://127.0.0.1:4444/selenium-grid/ 访问。

$ docker run -d -p 4444:4444 -e SE_SUB_PATH=/selenium-grid/ --name selenium-hub selenium/hub:4.47.0-20260808

设置屏幕分辨率

默认情况下,节点启动时的屏幕分辨率为 1920 x 1080,颜色深度为 24 位,dpi 为 96。 启动容器时,可以通过指定 SE_SCREEN_WIDTHSE_SCREEN_HEIGHTSE_SCREEN_DEPTH 和/或 SE_SCREEN_DPI 环境变量来调整这些设置。

docker run -d -e SE_SCREEN_WIDTH=1366 -e SE_SCREEN_HEIGHT=768 -e SE_SCREEN_DEPTH=24 -e SE_SCREEN_DPI=74 selenium/standalone-firefox:4.47.0-20260808

网格 URL 与会话超时

在某些使用场景中,您可能需要为节点设置网格 URL,例如,当您希望访问 BiDi/CDP 端点时。
当您想要使用 Selenium 4 中新增的 RemoteWebDriver.builder()Augmenter() 时(因为它们会隐式建立 BiDi/CDP 连接),也需要进行此设置。您可以通过 SE_NODE_GRID_URL 环境变量来实现,例如 -e SE_NODE_GRID_URL=http://<hostMachine>:4444。如果您希望在会话执行期间查看实时视图,则必须设置此环境变量。

网格的默认会话超时时间为 300 秒,在此期间,会话可能会处于停滞状态,直至被终止。您可以使用 SE_NODE_SESSION_TIMEOUT 以秒为单位覆盖此值。

会话请求超时

新的会话请求在处理前会被放入会话队列中,并在队列中等待,直到在已注册的节点中找到匹配的插槽。但是,如果未找到插槽,新的会话请求可能会超时。默认情况下,请求在队列中的最长等待时间为 300 秒,之后将达到超时。此外,默认情况下每 5 秒会尝试处理一次请求。

您可以通过 Hub 和 SessionQueue 中的环境变量(SE_SESSION_REQUEST_TIMEOUTSE_SESSION_RETRY_INTERVAL)来覆盖这些值。例如,若要设置 500 秒的超时时间,可使用 SE_SESSION_REQUEST_TIMEOUT=500;若要设置 2 秒的重试间隔,可使用 SE_SESSION_RETRY_INTERVAL=2

提高每个容器的会话并发数

默认情况下,通过 SE_NODE_MAX_SESSIONS 环境变量配置为每个容器仅运行一个会话。您可以将此数量增加到最大可用处理器数量,这是因为当一个容器/浏览器拥有 1 个 CPU 来运行时,可获得更高的稳定性。

但是,如果您已对性能进行了评估,并基于评估结果认为每个容器可以执行更多会话,则可以通过将 SE_NODE_MAX_SESSIONS 设置为所需数量,并将 SE_NODE_OVERRIDE_MAX_SESSIONS 设置为 true 来覆盖最大限制。尽管如此,不建议运行的浏览器会话数超过可用处理器数量,因为这会导致资源过载。

当启用视频录制时,覆盖此设置会产生不良副作用,因为多个浏览器会话可能会被捕获到同一个视频中。

以无头模式运行

FirefoxChrome, 使用无头模式时,无需启动Xvfb服务器。

若要避免启动该服务器,可将 SE_START_XVFB 环境变量设置为 false(或除 true 外的其他任何值),例如:

$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
  -e SE_START_XVFB=false --shm-size="2g" selenium/node-chrome:4.47.0-20260808

如需了解更多信息,请参阅此 GitHub issue

注意:

  • 在新版 Chrome/Chromium(v127+)中,若要以 --headless=new 模式运行,需将 SE_START_XVFB 设置为 true
  • 在新版 Chrome/Chromium(v132+)中,--headless 仅在new 模式下运行,因此使用 --headless 模式时,需将 SE_START_XVFB 设置为 true

执行 N 个会话后停止 Node/Standalone

在某些环境中,如 Docker Swarm 或 Kubernetes,在执行 N 个测试后关闭 Node 或 Standalone 容器非常有用。例如,这可用于在 Kubernetes 中终止 pod,然后在 N 个会话后扩展一个新的 pod。将环境变量 SE_DRAIN_AFTER_SESSION_COUNT 设置为大于零的值即可启用此行为。

$ docker run -e SE_DRAIN_AFTER_SESSION_COUNT=5 --shm-size="2g" selenium/standalone-firefox:4.47.0-20260808

使用前面的命令,Standalone 容器将在执行完 5 个会话后关闭。

浏览器残留自动清理

在长时间运行的容器中,浏览器可能会留下一些残留文件。这些可能是已完成但未能完全停止浏览器的作业所产生的僵死浏览器进程,或是写入 /tmp 文件系统的临时文件(尤其是基于 Chrome 的浏览器)。为避免这些残留占用容器中的进程 ID 和文件系统等资源,节点容器中运行着一个每小时执行一次的自动清理脚本。此脚本将清理旧进程和旧临时文件。默认情况下,此功能处于禁用状态。启用后,它将清理运行超过 2 小时的浏览器以及超过 1 天的文件。可通过以下环境变量启用并调整这些设置:

  • SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP:默认值为 false,设为 true 以启用清理功能。
  • SE_BROWSER_LEFTOVERS_INTERVAL_SECS:默认值为 3600(1 小时),清理间隔(以秒为单位)。
  • SE_BROWSER_LEFTOVERS_PROCESSES_SECS:默认值为 7200(2 小时),运行时间超过此值的浏览器将被终止。
  • SE_BROWSER_LEFTOVERS_TEMPFILES_DAYS:默认值为 1(1 天),基于 Chrome 的浏览器在 /tmp 中生成的文件将在指定天数后被删除(使用 Firefox 时此设置被忽略)。

如果您使用 Selenium 进行长时间运行的会话,且预期浏览器运行时间超过 2 小时,要么不要将 SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP 设置为 true(保持默认值 false),要么调整 SE_BROWSER_LEFTOVERS_PROCESSES_SECS 以设置一个高于您预期的长时间运行浏览器进程的值。

$ docker run -e SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP=true --shm-size="2g" selenium/node-chrome:4.47.0-20260808

使用前面的命令,将启用清理功能并采用默认时间设置。

$ docker run -e SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP=true \
-e SE_BROWSER_LEFTOVERS_INTERVAL_SECS=7200 \
-e SE_BROWSER_LEFTOVERS_PROCESSES_SECS=3600 \
-e SE_BROWSER_LEFTOVERS_TEMPFILES_DAYS=2 \
--shm-size="2g" selenium/node-chrome:4.47.0-20260808

使用前面的命令,清理功能将被启用,但会每 2 小时运行一次(而非 1 小时),会终止运行超过 1 小时的浏览器(而非 2 小时),并会删除超过 2 天的临时文件(而非 1 天)。


在控制台日志中屏蔽敏感信息

密码、密钥等少数变量的输出会在控制台日志中被屏蔽。出于调试目的,你可以通过将 SE_MASK_SECRETS 设置为 false 来禁用此功能。

创建 bash 脚本时,你可以使用 echo "Current value is $(mask ${YOUR_VARIABLE}) 语法来屏蔽输出。

SE_MASK_SECRETS_MIN_LENGTH 的默认值为 3。这意味着长字符串将被屏蔽为 ***,以避免因暴露长度而遭受暴力攻击。

安全连接

默认情况下,镜像中 /opt/selenium/secrets 目录下提供了默认的自签名证书,包括:

  • server.jks:启动服务器时,通过系统属性 javax.net.ssl.trustStore 为 JVM 配置的信任库文件。
  • server.pass:包含通过系统属性 javax.net.ssl.trustStorePassword 为 JVM 配置的信任库密码的文件。
  • tls.crt:用于 https 连接的服务器证书,设置到 Selenium 选项 --https-certificate
  • tls.key:用于 https 连接的服务器私钥(PKCS8 格式),设置到 Selenium 选项 --https-private-key

可通过以下环境变量配置安全连接:

环境变量 默认值 所属选项 描述
SE_ENABLE_TLS false 使用默认配置启用安全连接
SE_JAVA_SSL_TRUST_STORE /opt/selenium/secrets/server.jks JVM
SE_JAVA_SSL_TRUST_STORE_PASSWORD /opt/selenium/secrets/server.pass JVM
SE_JAVA_DISABLE_HOSTNAME_VERIFICATION true JVM 为内部组件禁用主机检查
SE_HTTPS_CERTIFICATE /opt/selenium/secrets/tls.crt Selenium 设置到命令行选项 --https-certificate
SE_HTTPS_PRIVATE_KEY /opt/selenium/secrets/tls.key Selenium 设置到命令行选项 --https-private-key

通过卷挂载,你可以用自己的证书替换默认证书。

客户端也需要信任自签名证书(将其添加到系统范围的受信任 CA bundle 中),以避免创建 RemoteWebDriver 时出现与 SSL 握手相关的错误消息。

参考示例:docker-compose-v3-full-grid-secure.yml

浏览器语言和区域设置

不同浏览器通过绑定设置语言和区域的方式各不相同。

Firefox

通过绑定创建 WebDriver 时,可通过设置配置文件首选项来将 Firefox 配置为使用特定语言和区域。此外,需要安装语言包作为附加组件,浏览器 UI 语言才能生效。例如,要将浏览器语言和区域设置为 vi-VN,可按照以下步骤操作:

获取所需语言的最新 Firefox 语言包,例如 https://download.mozilla.org/?product=firefox-langpack-latest-SSL&lang=vi。然后,在创建 RemoteWebDriver 实例时,可以将该语言包作为附加组件进行安装。

profile = webdriver.FirefoxProfile()
profile.set_preference('intl.accept_languages', 'vi-VN,vi')
profile.set_preference('intl.locale.requested', 'vi-VN,vi')
options = FirefoxOptions()
options.profile = profile
driver = webdriver.Remote(options=options, command_executor="http://selenium-hub:4444/wd/hub")
webdriver.Firefox.install_addon(driver, "/local/path/to/vi.xpi")
driver.get('https://google.com')

有一个脚本可用于获取特定 Firefox 版本的所有可用语言包。你可以运行此脚本来将语言包获取到你的源代码中。例如:

FIREFOX_VERSION=$(docker run --rm --entrypoint="" selenium/node-firefox:latest firefox --version | awk '{print $3}') \
&& ./NodeFirefox/get_lang_package.sh ${FIREFOX_VERSION} /local/path/to/download

或者,您可以将容器目录 $(readlink -f $(which firefox)))/distribution/extensions 挂载到主机目录,以访问容器中预构建的扩展包,以便在测试脚本中使用。

容器内进程管理

Supervisor 用于管理容器内的进程和日志。以下环境变量可用于设置 supervisord 的部分配置:

环境变量 默认值 supervisord 配置项
SE_SUPERVISORD_LOG_LEVEL info supervisord.loglevel
SE_SUPERVISORD_CHILD_LOG_DIR /tmp supervisord.childlogdir
SE_SUPERVISORD_LOG_FILE /tmp/supervisord.log supervisord.logfile
SE_SUPERVISORD_PID_FILE /tmp/supervisord.pid supervisord.pidfile

构建镜像

克隆仓库,然后在项目目录根目录下运行以下命令即可构建所有内容:

$ VERSION=local make build

如果需要配置环境变量来构建镜像(例如 HTTP 代理),只需设置一个名为 BUILD_ARGS 的环境变量,其中包含要传递给 docker 上下文的其他变量(这仅适用于 docker >= 1.9)

$ BUILD_ARGS="--build-arg http_proxy=http://acme:3128 --build-arg https_proxy=http://acme:3128" make build

注意:如果省略 VERSION=local,构建镜像时将使用已发布的版本号,但会将日期替换为当前日期。

如果希望使用主机的 UID/GID 构建镜像,只需设置环境变量 BUILD_ARGS

$ BUILD_ARGS="--build-arg UID=$(id -u) --build-arg GID=$(id -g)" make build

如果您希望使用不同的默认用户名/密码构建镜像,只需设置环境变量 BUILD_ARGS

$ BUILD_ARGS="--build-arg SEL_USER=yourseluser --build-arg SEL_PASSWD=welcome" make build

使用特定版本构建镜像

基于最新的 Dockerfile(通过克隆仓库并从项目目录根目录操作),您可以使用 Selenium Grid 和浏览器版本的特定组合来构建镜像。

例如,您希望构建 node-chromestandalone-chrome 镜像,其中 Grid 基础版本为 4.17.0,Chrome 浏览器版本分别为 119120123

$ ./tests/build-backward-compatible/bootstrap.sh 4.17.0 119,120,123 chrome

通常情况下,该脚本接受以下参数:

  • $1(必填):Selenium Grid 版本。详细信息从矩阵 文件 中获取
  • $2(必填):浏览器主版本号,多个值用逗号分隔。详细信息从矩阵 文件 中获取
  • $3(可选):浏览器名称。如果未提供,将遍历所有浏览器(chromeedgefirefox
  • $4(可选):将镜像推送到 registry。默认值为 false。如果希望将镜像推送到 registry,请将其设置为 true(运行脚本前需完成 Docker 登录到您的命名空间)。

要更新浏览器版本矩阵,您可以运行以下命令:

make update_browser_versions_matrix

要设置镜像的命名空间,您可以在运行脚本前设置环境变量 NAME。例如:

$ export NAME=artifactory.yourcompany.com/selenium
$ ./tests/build-backward-compatible/bootstrap.sh 4.17.0 119,120,123 chrome

运行脚本后,您将看到带有完整标签的镜像列表,可按照标签约定来固定特定的 Grid 和浏览器版本。


升级镜像中的浏览器版本

Selenium 服务器、浏览器和驱动程序已预先安装在镜像中。如果您希望保持当前 Selenium 版本不变,仅将浏览器及其驱动程序升级到最新版本,可按照以下步骤操作:

克隆仓库,并从项目目录根目录运行以下命令进行升级:

$ VERSION=$EXPECTED_SELENIUM_VERSION make chrome_upgrade_version

例如:VERSION=4.16.1 make chrome_upgrade_version

新镜像的标签为$VERSION_YYYYMMDD,其中YYYYMMDD是当前日期。

$ VERSION=$SELENIUM_VERSION make firefox_upgrade_version
$ VERSION=$SELENIUM_VERSION make edge_upgrade_version

您可以参考 Makefile 文件中的详细命令。


升级镜像中的浏览器和驱动版本

镜像名称 支持情况
node-chrome, standalone-chrome

使用此功能有两种方式。

  1. 在运行时(启动容器时)升级 Chrome 和 ChromeDriver。将容器环境变量 SE_UPDATE_CHROME_COMPONENTS 设置为 true。例如:

    docker run -d -p 4444:4444 -p 5900:5900 --shm-size="2g" -e SE_UPDATE_CHROME_COMPONENTS=true selenium/standalone-chrome:latest
    

    权衡: 请注意,容器重启后,更新的二进制文件将会丢失,除非您在构建容器过程中调用更新脚本(如下述第二种用法)。

  2. 通过复用镜像层并将 Chrome 和 ChromeDriver 升级到最新版本来构建您自己的镜像 创建如下简单的 Dockerfile:

    FROM --platform=linux/amd64 selenium/standalone-chrome:latest
    RUN /opt/bin/update-chrome-components.sh
    
    • 选项 1:构建您自己的镜像标签
    docker buildx build --platform linux/amd64 -t selenium/standalone-chrome:my-latest .
    
    • 选项 2:在 docker compose 中使用 Dockerfile
    services:
      chrome:
        build:
          context: .
          dockerfile: Dockerfile
        image: selenium/standalone-chrome:my-latest
        # 根据需要添加环境变量、端口、卷等
    

等待 Grid 准备就绪

最佳实践是先检查 Grid 是否已启动并准备好接收请求,这可以通过检查 /wd/hub/status 端点来实现。

一个由一个 hub 和两个节点组成的就绪 Grid 可能如下所示:

{
  "value": {
    "ready": true,
    "message": "Selenium Grid ready.",
    "nodes": [
      {
        "id": "6c0a2c59-7e99-469d-bbfc-313dc638797c",
        "uri": "http:\u002f\u002f172.20.1.3:5555",
        "maxSessions": 4,
        "stereotypes": [
          {
            "capabilities": {
              "browserName": "firefox"
            },
            "count": 4
          }
        ],
        "sessions": [
        ]
      },
      {
        "id": "26af3363-a0d8-4bd6-a854-2c7497ed64a4",
        "uri": "http:\u002f\u002f172.20.1.4:5555",
        "maxSessions": 4,
        "stereotypes": [
          {
            "capabilities": {
              "browserName": "chrome"
            },
            "count": 4
          }
        ],
        "sessions": [
        ]
      }
    ]
  }
}

"ready": true 值表示 Grid 已准备好接收请求。可以在运行任何测试之前通过脚本轮询此状态,或者在启动 docker 容器时将其添加为 HEALTHCHECK

为 Grid 添加 HEALTHCHECK

镜像中包含的脚本 check-grid.sh 可用于轮询 Grid 状态。

此示例每 15 秒检查一次 Grid 状态,检查时超时时间为 30 秒,最多重试 5 次,之后容器将被标记为不健康。请根据需要调整这些值,(如有必要)将 --host--port 参数替换为您环境中使用的参数。

$ docker network create grid
$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub \
  --health-cmd='/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444' \
  --health-interval=15s --health-timeout=30s --health-retries=5 \
  selenium/hub:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-chrome:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-edge:4.47.0-20260808
$ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
    selenium/node-firefox:4.47.0-20260808

注意: \ 行分隔符在基于 Windows 的终端上不起作用,请尝试使用 ^ 或反引号。

可以通过执行 docker ps 并验证 (healthy)|(unhealthy) 状态来检查容器的健康状态,或者通过以下方式进行检查:

$ docker inspect --format='{{json .State.Health.Status}}' selenium-hub
"healthy"

使用 bash 脚本等待 Grid 就绪

Docker 中一个常见的问题是,容器正在运行并不总是意味着其中的应用已准备就绪。 解决此问题的一种简单方法是使用“wait-for-it”脚本,更多信息可参见此处

以下脚本是使用 bash 实现此功能的示例,但如果您想使用编写测试所用的编程语言来实现,原理是相同的。 在下面的示例中,该脚本将每秒轮询一次状态端点。如果 Grid 在 30 秒内未准备就绪,脚本将以错误代码退出。

#!/bin/bash
# wait-for-grid.sh

set -e
url="http://localhost:4444/wd/hub/status"
wait_interval_in_seconds=1
max_wait_time_in_seconds=30
end_time=$((SECONDS + max_wait_time_in_seconds))
time_left=$max_wait_time_in_seconds

while [ $SECONDS -lt $end_time ]; do
    response=$(curl -sL "$url" | jq -r '.value.ready')
    if [ -n "$response"  ]  && [ "$response" ]; then
        echo "Selenium Grid is up - executing tests"
        break
    else
        echo "Waiting for the Grid. Sleeping for $wait_interval_in_seconds second(s). $time_left seconds left until timeout."
        sleep $wait_interval_in_seconds
        time_left=$((time_left - wait_interval_in_seconds))
    fi
done

if [ $SECONDS -ge $end_time ]; then
    echo "Timeout: The Grid was not started within $max_wait_time_in_seconds seconds."
    exit 1
fi

需要通过 apt-get 安装 jq,否则脚本会一直打印 Waiting 而无法完成执行。

注意: 如有需要,请将 localhost4444 替换为您环境中的正确值。此外,此脚本会无限期轮询,您可能需要对其进行调整并设置超时时间。

假设执行测试的常规命令是 mvn clean test。以下是使用上述脚本执行测试的方法:

$ ./wait-for-grid.sh && mvn clean test

这样,脚本将轮询直到 Grid 准备就绪,然后您的测试将开始。


为基于 Chromium 的浏览器安装证书

默认情况下,基础镜像已安装 libnss3-tools 并初始化了 /home/seluser/.pki/nssdb,因此您可以以无 root 权限添加证书。 如果您需要安装自定义证书、CA、中间 CA 或客户端证书(例如,企业内部 CA),可以从 selenium 节点镜像创建自己的 docker 镜像。 基于 Chromium 的浏览器使用 nssdb 作为证书存储。 您可以在 Dockerfile 中按以下方式安装所有所需的内部证书:

镜像中包含一个实用脚本,可用于将您的证书添加到 nssdb 存储和 CA 捆绑包中。 该脚本为 /opt/bin/add-cert-helper.sh

  • 创建一个 Dockerfile,以 selenium 节点镜像为基础,将脚本复制到容器中并执行它。 例如,Dockerfile

  • 如果您需要创建一组不同的证书和节点镜像。您可以创建一个引导脚本一次性完成。 例如,bootstrap.sh

可以使用以下命令测试上述示例:

make test_custom_ca_cert
# ./tests/customCACert/bootstrap.sh

您可以在此处找到更多信息。

这样,证书将被安装,节点将像以前一样自动启动。


替代方法:向现有的基于 Selenium 的浏览器镜像添加证书

作为替代方案,您可以将证书文件添加到现有的 Selenium 镜像中。这个实用示例假设您有一个已知的镜像可用作构建镜像,并且有办法将新镜像发布到本地 docker 仓库。

本示例使用基于 RedHat 的发行版作为构建镜像(Rocky Linux),但您也可以选择任何 Linux 镜像。请注意,不同发行版的构建指令会有所不同。您可以参考前一个示例中的 Ubuntu 相关说明。

该示例还假设您的内部 CA 已位于 /etc/pki/ca-trust/source/anchors/YOUR_CA.pem,这是 Rocky Linux 的默认位置。或者,您也可以从主机提供这些文件并将它们复制到构建镜像中。

对于 Chrome 和 Edge 浏览器,操作步骤相同,只需调整镜像名称(node-chrome 或 node-edge):

# Get a standard image for creating nssdb file
FROM rockylinux:8.6 as build
RUN yum install -y nss-tools
RUN mkdir -p -m755 /seluser/.pki/nssdb \
    && certutil -d sql:/seluser/.pki/nssdb -N --empty-password \
    && certutil -d sql:/seluser/.pki/nssdb -A -t "C,," -n YOUR_CA -i /etc/pki/ca-trust/source/anchors/YOUR_CA.pem \
    && chown -R 1200:1201 /seluser

# Start from Selenium image and add relevant files from build image
FROM selenium/node-chrome:4.47.0-20260808
USER root
COPY --from=build /seluser/ /home/seluser/
USER seluser

Firefox 示例:

# Get a standard image for working on
FROM rockylinux:8.6 as build
RUN mkdir -p "/distribution" "/certs" && \
    cp /etc/pki/ca-trust/source/anchors/YOUR_CA*.pem /certs/ && \
    echo '{ "policies": { "Certificates": { "Install": ["/opt/firefox-latest/YOUR_CA.pem"] }} }' >"/distribution/policies.json"

# Start from Selenium image and add relevant files from build image
FROM selenium/node-firefox:4.47.0-20260808
USER root
COPY --from=build /certs /opt/firefox-latest
COPY --from=build /distribution /opt/firefox-latest/distribution
USER seluser

调试

本项目使用 x11vnc 作为 VNC 服务器,方便用户查看容器内部的运行情况。用户可通过以下两种方式连接该服务器:

使用 VNC 客户端

VNC 服务器监听 5900 端口,您可以使用 VNC 客户端进行连接。您可以将 5900 端口映射到任意空闲的外部端口。

内部 5900 端口保持不变,因为这是容器内运行的 VNC 服务器的配置端口。如果您想使用 --net=host,可以通过 SE_VNC_PORT 环境变量覆盖该端口。

以下是独立镜像的示例,相同的概念也适用于节点镜像。

$ docker run -d -p 4444:4444 -p 5900:5900 --shm-size="2g" selenium/standalone-chrome:4.47.0-20260808
$ docker run -d -p 4445:4444 -p 5901:5900 --shm-size="2g" selenium/standalone-edge:4.47.0-20260808
$ docker run -d -p 4446:4444 -p 5902:5900 --shm-size="2g" selenium/standalone-firefox:4.47.0-20260808

然后,您可以在 VNC 客户端中使用:

  • 端口 5900 连接到 Chrome 容器
  • 端口 5901 连接到 Edge 容器
  • 端口 5902 连接到 Firefox 容器

如果出现要求输入密码的提示,密码为:secret。如果您希望更改此密码,可以设置环境变量 SE_VNC_PASSWORD

如果您希望运行 VNC 时不进行密码验证,可以设置环境变量 SE_VNC_NO_PASSWORD=true

如果您希望以仅查看模式运行 VNC,可以设置环境变量 SE_VNC_VIEW_ONLY=true

如果您希望修改 VNC 服务器进程的打开文件描述符限制,可以设置环境变量 SE_VNC_ULIMIT=4096

使用浏览器(无需 VNC 客户端)

本项目使用 noVNC 允许用户通过浏览器直观地查看容器活动。如果您无法在机器上安装 VNC 客户端,这会非常有用。端口 7900 用于启动 noVNC,因此您需要使用浏览器连接到该端口。

与上一节类似,您可以将端口 7900 映射到任何您希望的空闲外部端口。如果您想使用 --net=host,也可以通过 SE_NO_VNC_PORT 环境变量覆盖该端口。

以下是独立镜像的示例,相同的概念也适用于节点镜像。

$ docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:4.47.0-20260808
$ docker run -d -p 4445:4444 -p 7901:7900 --shm-size="2g" selenium/standalone-edge:4.47.0-20260808
$ docker run -d -p 4446:4444 -p 7902:7900 --shm-size="2g" selenium/standalone-firefox:4.47.0-20260808

然后,你可以在浏览器中使用以下链接:

如果出现要求输入密码的提示,密码为:secret

禁用 VNC

如果你的资源不足,或者根本不需要检查运行中的会话,可以完全不运行 VNC。只需在网格启动时设置 SE_START_VNC=false 环境变量即可。


网格中的追踪

要在 Selenium Grid 容器中启用追踪,可以执行以下命令:

docker network create grid
docker run -d -p 16686:16686 -p 4317:4317 --net grid --name jaeger jaegertracing/all-in-one:1.54
docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.47.0-20260808
docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
	-e SE_ENABLE_TRACING=true \
	-e SE_OTEL_TRACES_EXPORTER=otlp \
	-e SE_OTEL_EXPORTER_ENDPOINT=http://jaeger:4317 \
    selenium/node-chrome:4.47.0-20260808
docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
	-e SE_ENABLE_TRACING=true \
	-e SE_OTEL_TRACES_EXPORTER=otlp \
	-e SE_OTEL_EXPORTER_ENDPOINT=http://jaeger:4317 \
    selenium/node-edge:4.47.0-20260808
docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \
    --shm-size="2g" \
	-e SE_ENABLE_TRACING=true \
	-e SE_OTEL_TRACES_EXPORTER=otlp \
	-e SE_OTEL_EXPORTER_ENDPOINT=http://jaeger:4317 \
    selenium/node-firefox:4.47.0-20260808

您也可以参考以下 docker compose yaml 文件来启动简单网格或动态网格。

您可以查看 Jaeger UI 并跟踪您的请求。

默认情况下,网格组件中启用了跟踪功能。如果没有跟踪导出器端点,它将查找本地实例,例如 localhost/[0:0:0:0:0:0:0:1]:4117。 在容器日志中,您可以看到如下几行内容:

ERROR (ThrottlingLogger.dolog) Failed to export spans.
  The request could not be executed. Error message: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4117
  java.net.ConnectException: Failed to connect to localhost/[0:0:0:0:0:0:0:1]:4317 
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:297)
at okhttp3.internal.connection. ExchangeFinder.findConnection (Exchangefinder.kt: 226)
at okhttp3.internal.connection.okhttps.internal.connection.RealConnection.connect(RealConnection.kt:207)

在这种情况下,只需为所有组件容器设置 SE_ENABLE_TRACING=false 即可禁用追踪(每个组件会导出自己的追踪数据)。


故障排除

所有输出都会发送到标准输出,因此可以通过运行以下命令进行检查:

$ docker logs -f <container-id|container-name>

您可以通过向容器传递环境变量来增加日志输出:

SE_OPTS="--log-level FINE"

--shm-size="2g"

为什么需要 --shm-size 2g

这是避免浏览器在 docker 容器内崩溃的已知解决方法,以下是相关文档化问题链接: ChromeFirefox。 2GB 的共享内存大小是一个经验值,但实践证明效果良好。您的具体使用场景可能需要不同的值,建议根据实际需求调整此参数。

无头模式

如果您遇到以下 Selenium 异常:

Message: invalid argument: can't kill an exited process

Message: unknown error: Chrome failed to start: exited abnormally

[DriverServiceSessionFactory.apply] - Error while creating session with the driver service. Stopping driver service: java.util.concurrent.TimeoutException

原因可能是您将 SE_START_XVFB 环境变量设置为 false,但忘记以无头模式运行 Firefox、Chrome 或 Edge。

挂载卷以获取下载文件

一个常见场景是将卷挂载到浏览器容器,以便获取下载的文件。 在 Windows 和 macOS 系统上,此操作可以顺利进行,但在 Linux 系统上需要一些额外的解决方法才能实现。有关更多详细信息,请查看此文档完善的 issue

例如,在 Linux 系统中,您可能会通过以下方式启动容器:

docker run -d -p 4444:4444 --shm-size="2g" \
  -v /home/ubuntu/files:/home/seluser/Downloads \
  selenium/standalone-chrome:4.47.0-20260808

这会将主机的 /home/ubuntu/files 目录挂载到容器内的 /home/seluser/Downloads(默认浏览器的下载目录)。问题在于,卷会以 root 用户身份挂载;因此,以 seluser 用户身份运行的浏览器无法向该目录写入文件。这是因为 Docker 在 Linux 中就是这样挂载卷的,更多详细信息请参见此 issue

解决此问题的方法是在主机上创建一个目录,并在挂载卷之前更改其权限。根据您的用户权限,您可能需要对其中一些命令使用 sudo

mkdir /home/ubuntu/files
chown 1200:1201 /home/ubuntu/files

完成此操作后,您应该能够将文件下载到挂载目录。如果您有更好的解决方法,请向我们提交拉取请求!

挂载卷以检索视频文件

与挂载卷以检索下载文件的方式类似。对于视频文件,您可能需要执行相同的操作

mkdir /tmp/videos
chown 1200:1201 /tmp/videos

每个会话的 WebSocket 连接耗尽

org.openqa.selenium.remote.http.ConnectionFailedException: JdkWebSocket 初始请求执行错误`

此问题已在 #2850 中报告。 实际上,从 Grid 版本 v4.26.0+ 开始,节点 CLI 选项 --connection-limit-per-sessionSE_NODE_CONNECTION_LIMIT_PER_SESSION 环境变量)的默认值设置为 10。设 X 为每个会话的最大 WebSocket 连接数。这将确保一个会话不会耗尽主机的连接限制。WebSocket 连接可能来自启用的 CDP、BiDi。

您的测试场景或测试框架实现可能会为每个会话创建超过 X 个连接,这将导致上述错误。您可以优化实现以减少每个会话的连接数,或者通过将环境变量 SE_NODE_CONNECTION_LIMIT_PER_SESSION 设置为高于 10 的值来增加限制,以允许每个会话有更多连接。

星标历史

Stargazers over time

项目介绍

提供了一种简洁的方法,使用Docker运行Selenium Grid,支持Chrome、Firefox和Edge浏览器,从而简化了浏览器自动化的实施过程。【此简介由AI生成】

定制我的领域
2408.65 K2.55 K访问 GitHub