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

借助Jib获取特定版本镜像(Maven、Docker、Testcontainers)

关于Testcontainers测试夹具与ImageResolver的疑问

代码背景

我们使用Testcontainers创建测试夹具,原有代码被注释,同事给出了修改建议:

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

public class SalesforceFixture extends GenericContainer<SalesforceFixture> {

  private static final String APPLICATION_NAME = "salesforce-emulator";

  public SalesforceFixture() {
    // super(ImageResolver.resolve(APPLICATION_NAME));
    super(DockerImageName.parse("gcr.io/ad-selfserve/salesforce-emulator:latest"));
    ...
  }

...

同事的注释:

这部分我不太清楚。[ImageResolver]会获取模拟器的特定版本而非latest版本,但需要docker-info文件,Jib不会自动生成该文件(不过我认为它可以生成)。

梳理的信息与疑问

  • SalesforceFixture是供其他项目编写测试用的类,会在Docker中启动容器运行模拟真实服务API的模拟器,确保测试代码在生产环境能正常运行。
  • 研究了自定义的ImageResolver类,其核心代码如下:
    public static String resolve(String applicationName, File... roots) {
      Stream<File> searchPaths = Arrays.stream(roots).flatMap((value) -> {
        return Stream.of(new File(value, "../" + applicationName), new File(value, applicationName));
      });
      Optional<File> buildFile = searchPaths.flatMap((searchFile) -> {
        if (searchFile.exists()) {
          File imageFile = new File(searchFile + File.separator + "/target/docker/image-name");
          if (imageFile.exists()) {
            return Stream.of(imageFile);
          }
        }
    
        return Stream.empty();
      }).findAny();
      InputStream build = (InputStream)buildFile.map(ImageResolver::fileStream).orElseGet(() -> {
        return searchClasspath(applicationName);
      });
      if (build != null) {
        try {
          return IOUtils.toString(build, Charset.defaultCharset()).trim();
        } catch (IOException var6) {
          throw new RuntimeException("An exception has occurred while reading build file", var6);
        }
      } else {
        throw new RuntimeException("Could not resolve target image for application: " + applicationName);
      }
    }
    
    疑问:它搜索的是哪个文件系统?是运行Java程序的本地电脑当前工作目录?容器内部?还是.jar文件内的目录结构?亦或是镜像仓库中的位置?
  • 同事所说的“特定版本号”与“latest”有什么区别?构建项目时生成的镜像就是latest,什么时候会存在旧版本镜像?
  • 是否意味着使用该镜像的项目无法通过Maven/pom.xml指定版本,始终会启动latest版本?

问题解答

1. ImageResolver的搜索范围

从代码逻辑来看:

  • 优先在本地文件系统中搜索:基于传入的roots参数(默认是当前工作目录),查找../applicationName或applicationName目录下的/target/docker/image-name文件。
  • 本地找不到时,会从当前Java程序的类路径(包括本地class文件、jar包内的资源)中查找对应资源。
  • 不会搜索容器内部或远程镜像仓库(如gcr.io),仅在运行测试的本地环境范围内查找。

2. 特定版本号与latest的差异

  • latest是Docker镜像的可变标签:每次新构建并推送镜像到仓库时,latest会被覆盖指向最新镜像,无法固定到某个特定版本。
  • 特定版本号(如v1.2.3、20240520-build123)是固定标签,每个版本对应唯一镜像,不会被后续构建覆盖,能确保测试使用的镜像版本稳定。
  • 旧版本镜像会保留在远程仓库中,项目迭代发布新版本后,旧版本镜像不会自动删除,可用于兼容性测试等场景。

3. Maven版本指定的问题

  • 原ImageResolver逻辑是读取本地构建生成的image-name文件,该文件由salesforce-emulator项目构建时生成(配置Jib可生成包含具体版本的镜像名称文件),能保证测试镜像版本与依赖的项目版本一致。
  • 改成硬编码latest后,确实无法通过Maven/pom.xml指定版本,测试会始终拉取仓库中最新的latest镜像,无法匹配项目依赖的特定版本。
  • 若要支持版本指定,应恢复ImageResolver逻辑,并配置Jib在构建salesforce-emulator时自动生成image-name文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:20:29