docker-selenium 如何用一条脚本给镜像挂上十几个标签别名?镜像标签发布机制完整解析
【免费下载链接】docker-seleniumProvides a simple way to run Selenium Grid with Chrome, Firefox, and Edge using Container Platform, making it easier to perform browser automation at scale项目地址: https://gitcode.com/GitHub_Trending/do/docker-selenium
docker-selenium 是把 Selenium Grid 与特定浏览器、驱动版本打包成镜像的项目,它的镜像标签发布全部由仓库根目录的 tag_and_push_browser_images.sh 一条脚本驱动。本文基于 Grid 4.34.0 上 Chrome 120 的一次真实发布记录,拆解120.0.6099.224-chromedriver-120.0.6099.109-grid-4.34.0-20250727这类长标签的每一段来源、历史版本为何只打部分标签,以及你想钉住浏览器版本时该拉哪一条。
🎯 想钉住浏览器版本,该拉哪条标签?
拉镜像的人通常不关心发布怎么做的,只关心"环境怎么锁死"。项目给出的选择惯例按粒度分档:
- 复现缺陷、验证回归:选最长的标签
<浏览器完整版本>-chromedriver-<驱动完整版本>-grid-<Grid版本>-<构建日期>,浏览器、驱动、Grid、日期四个维度一次锁住; - 只钉浏览器主版本:选短版本标签,如
selenium/standalone-chrome:120.0-20250727,版本段截成两段更省事; - 跟进最新 Grid 发布:可以直接用不带日期的裸标签,如
selenium/node-chrome:120.0——前提是那次发布走的是"最新版本"模式; - 使用已归档的 Grid 版本:一律选带构建日期后缀的标签,归档版本根本不会发
120.0这类裸标签。
这套惯例的动机写在 CHANGELOG/README.md:持续更新 Grid 核心的同时,允许用户为跨浏览器测试或规避特定版本的已知问题而把浏览器钉死在某个版本。该文件里的版本矩阵就是"哪个 Grid 版本提供哪个浏览器版本"的查询入口,每个 ✓ 都指向对应发布的 changelog。
顺着惯例看,自然冒出两个疑问:归档版本的标签为什么必须带日期?CI 里这批标签又如何保证是多架构、而不是在 runner 上退化成单架构?答案都在发布脚本里。
📦 真实记录:一条命令与一串输出
Grid 4.34.0 上 Chrome 120 的发布记录见 CHANGELOG/archived/4.34.0/chrome_120.md,执行命令与输出如下(版本回显行从略):
./tag_and_push_browser_images.sh 4.34.0 20250727 selenium false chrome true Tagged selenium/node-chrome:120.0.6099.224-chromedriver-120.0.6099.109-grid-4.34.0-20250727 Tagged selenium/standalone-chrome:120.0.6099.224-chromedriver-120.0.6099.109-grid-4.34.0-20250727 Tagged selenium/node-chrome:120.0.6099.224-chromedriver-120.0.6099.109-20250727 Tagged selenium/standalone-chrome:120.0.6099.224-chromedriver-120.0.6099.109-20250727 Tagged selenium/node-chrome:120.0.6099.224-20250727 Tagged selenium/standalone-chrome:120.0.6099.224-20250727 Tagged selenium/node-chrome:120.0-chromedriver-120.0-grid-4.34.0-20250727 Tagged selenium/standalone-chrome:120.0-chromedriver-120.0-grid-4.34.0-20250727 Tagged selenium/node-chrome:120.0-chromedriver-120.0-20250727 Tagged selenium/standalone-chrome:120.0-chromedriver-120.0-20250727 Tagged selenium/node-chrome:120.0-20250727 Tagged selenium/standalone-chrome:120.0-20250727node-chrome与standalone-chrome两个镜像各挂上六组标签,Tagged 行共 12 条。从这份记录能读出标签拼装的节奏:版本段以"完整版本(120.0.6099.224)+ 短版本(120.0)"成对出现,再分别搭配不同后缀。这些版本号是脚本凭空假设的吗?决定"只打六组"的开关又在哪?先回顾脚本运行之前发生了什么。
脚本跑起来之前:镜像构建与七个位置参数
tag_and_push_browser_images.sh 本身不构建任何镜像,它只负责打标签和推送。它要求带${VERSION}-${BUILD_DATE}标签的镜像(本例为4.34.0-20250727)已经存在于本地。这个镜像由 Makefile 里的*_upgrade_version目标产出:chrome_upgrade_version先用docker buildx build多架构构建node-chrome与standalone-chrome,再进容器跑 Selenium 服务器、google-chrome、chromedriver三条版本命令,校验打包进去的东西。打标签则由tag_and_push_browser_images目标触发,它按 chrome、chrome-for-testing、chromium、edge、firefox 顺序调用同一脚本。
脚本接受七个位置参数,全部由 Makefile 变量传入:
$1VERSION:Selenium Grid 版本,如4.34.0;$2BUILD_DATE:构建日期,YYYYMMDD格式;$3NAMESPACE:镜像命名空间;$4PUSH_IMAGE:docker tag之后是否执行docker push,默认false;$5BROWSER:浏览器类型;$6RELEASE_OLD_VERSION:是否按旧版本(归档)模式发布,默认false;$7PLATFORM:版本探测的目标平台,默认linux/amd64。
有个值得停顿的细节:脚本把第三个参数读进NAMESPACE之后,紧接着用NAMESPACE=${NAME:-selenium}覆盖了一次。实际生效的命名空间由NAME环境变量决定,未设置时回落selenium,第三个参数只活在日志第一行里。想以自定义命名空间发布,得设NAME,指望位置参数不会生效。
🧪 标签里的版本从哪来:脚本进容器"审讯"镜像
脚本不预设浏览器版本,而是直接运行已构建好的镜像把真实版本读出来。chrome 分支的两条命令:
CHROME_VERSION=$(docker run --platform ${PLATFORM} --rm ${NAMESPACE}/node-chrome:${TAG_VERSION} google-chrome --version | awk '{print $3}') CHROMEDRIVER_VERSION=$(docker run --platform ${PLATFORM} --rm ${NAMESPACE}/node-chrome:${TAG_VERSION} chromedriver --version | awk '{print $2}')google-chrome --version输出Google Chrome 120.0.6099.224,取第 3 个字段得浏览器版本;chromedriver --version首行形如ChromeDriver 120.0.6099.109 ...,取第 2 个字段得驱动版本——这就是日志里Chrome version -> 120.0.6099.224与ChromeDriver version -> 120.0.6099.109的出处。短版本由内置的short_version()按.切分取前两段,得到120.0。
"打标签时读真实版本"与构建阶段的版本校验形成呼应,两处都以镜像实际输出为准。另有一个细节要留意:--platform只在 chrome 与 chrome-for-testing 两个分支显式传入,chromium、edge、firefox 的探测并不指定平台,跨架构发布时留意这个行为差异。
为什么这次只有六组标签?拆解 6 + 4 的标签矩阵
版本拿到手,下一步是拼标签数组。chrome 分支固定拼出六组基础标签(其余浏览器同构,仅驱动段换成 edgedriver 或 geckodriver):
- 完整浏览器版本 + 完整驱动版本 +
grid-<Grid版本>-<构建日期>,四维度全锁,精度最高; - 完整浏览器版本 + 完整驱动版本 + 构建日期;
- 完整浏览器版本 + 构建日期;
- 短浏览器版本 + 短驱动版本 +
grid-<Grid版本>-<构建日期>; - 短浏览器版本 + 短驱动版本 + 构建日期;
- 短浏览器版本 + 构建日期。
在此之外还有一组受开关控制的标签:仅当RELEASE_OLD_VERSION为false(正在发布的是最新Grid 版本)时,才追加四条不带日期的裸标签——<完整版本>-chromedriver-<完整驱动>、<完整版本>、<短版本>-chromedriver-<短驱动>、<短版本>。所以一次最新版本发布会打出 10 组标签 × 2 个镜像。
回到这条记录:命令第 6 个参数是true,4.34.0 已降为归档版本,走的是旧版本发布模式,于是只发六组基础标签。设计动机是消歧:120.0这类裸标签不含 Grid 版本信息,若多个 Grid 版本先后打同一个裸标签,会互相覆盖或把使用者带偏。归档版本因此只允许发天然唯一、带构建日期后缀的标签。
🔄 同一个镜像,多份架构:retag() 的两条执行路径
上述所有标签最终都流入retag()函数,它按环境变量PROMOTE_TAGS分叉成两条路径:
- 默认路径:本地执行
docker tag,给4.34.0-20250727基础镜像追加别名;若PUSH_IMAGE=true,再docker push上注册表。 - Promote 路径:CI(deploy.yml)决定"沿用测试过的镜像、不再重建"时设置
PROMOTE_TAGS=true,脚本改用docker buildx imagetools create --tag <新标签> <源索引>,在清单索引层面做注册表到注册表的标签复制;若同时设置PROMOTE_GHCR_NAMESPACE,同一次调用还会镜像到 GHCR 命名空间。
为什么绕道 imagetools?脚本注释解释了:docker tag要求镜像在本地,而 runner 上的docker pull只带回 runner 自身架构的镜像,打出来的浏览器标签就成了单架构,它别名的发布标签却偏偏是多架构的;imagetools直接操作索引,多架构清单原样保留。注释还说明了为什么 GHCR 镜像化不放到 Makefile 的tag_and_push_browser_images_ghcr目标里后置处理——那个目标靠docker images枚举本地镜像逐个镜像,而 promote 路径下本地仓库是空的,无图可枚举。
if [ "${PROMOTE_TAGS}" = "true" ]; then local __targets=(--tag "${NAMESPACE}/${__image}:${__tag}") if [ -n "${PROMOTE_GHCR_NAMESPACE}" ]; then __targets+=(--tag "${PROMOTE_GHCR_NAMESPACE}/${__image}:${__tag}") fi docker buildx imagetools create "${__targets[@]}" "${__source}" return fi docker tag "${__source}" "${NAMESPACE}/${__image}:${__tag}"⚠️ 速查:选标签与跑脚本的坑
- 归档版本别找裸标签。
RELEASE_OLD_VERSION=true时不存在120.0、120.0.6099.224这类标签,这是有意设计而非漏发;用带日期后缀的那条。 - 命名空间听
NAME的。第三个位置参数读完即被NAMESPACE=${NAME:-selenium}覆盖,自定义命名空间必须走环境变量。 - 平台探测只覆盖两个分支。
--platform只传给 chrome 与 chrome-for-testing,其他浏览器探测不指定平台。 - 组合无全量保证。CHANGELOG/README.md 的矩阵明确说明并非每个"Grid × 浏览器"组合都经过完整测试,选组合前先自行评估。
- 找不到就查矩阵。确认"哪个 Grid 版本提供哪个浏览器版本"直接查版本矩阵,每个 ✓ 指向的发布记录里,
Tagged行就是该拉的镜像标签。 - 客户端能力配合。镜像跑起来后,Selenium 客户端可用
browserName/browserVersion能力向 Grid 请求匹配节点,标签里的版本号即该节点实际可用的版本。
【免费下载链接】docker-seleniumProvides a simple way to run Selenium Grid with Chrome, Firefox, and Edge using Container Platform, making it easier to perform browser automation at scale项目地址: https://gitcode.com/GitHub_Trending/do/docker-selenium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考