测试容器,在构建 Dockerfile 之前尝试从本地注册表加载
Testcontainers, try to load from local registry before build a Dockerfile
我正在使用带有 Spring-Boot 的 Tescontainer 开发一些测试用例,以便启动 MS-SQL dockerized 数据库。这是一个巨大的数据库,需要大约 40 分钟才能在 docker 运行 进程中恢复。
我处理这张图片的步骤是:
- 使用模式和数据脚本将其标记为“db”构建 Dockerfile。
- 运行 容器并等待大约 40 分钟以恢复数据库。
- 提交带有“db-ready”标签的容器。
我期望的行为是测试用例尝试 运行 来自“db-ready”图像的 cointainer,如果失败,则直接从 Dockerfile 构建图像。我试过的代码看起来像:
public static CustomMSSqlContainer getInstance() {
if (container == null) {
try {
container = new CustomMSSqlContainer("myproject:db-ready");
}catch(Exception ex) {
container = new CustomMSSqlContainer(new ImageFromDockerfile().withFileFromClasspath("Dockerfile", "docker/Dockerfile")
.withFileFromClasspath("schema.sql", "docker/schema.sql")
.withFileFromClasspath("entrypoint.sh", "docker/entrypoint.sh")
.withFileFromClasspath("data.sql", "docker/data.sql")
.withFileFromClasspath("data-init.sql", "docker/data-init.sql")
.withFileFromClasspath("start.sh", "docker/start.sh"));
}
container.waitingFor(Wait.forLogMessage("Database ready\n", 1)
.withStartupTimeout(Duration.ofHours(1)))
.withExposedPorts(1433);
}
return (CustomMSSqlContainer)container;
}
当然,这段代码并不像我预期的那样工作。
有什么建议吗?
我们是如何解决这个问题的
我们这样做的方法是仅在 Main/Dev 分支 上构建自定义图像。这样:
- 我们不需要 try-catch;
- 我们只在实际需要时构建一个新容器(在合并请求批准更改并合并到主分支之后);
- 此容器的构建仅在 CI 管道上完成(因此人们不必也不能随机推送到容器注册表)
这是一个使用 JUnit 测试的示例(在此示例中禁用,但您可以使用 Spring 配置文件来启用它):
@Test
@Disabled("Should be run only with certain profiles ;)")
public void pushNewImage() throws InterruptedException {
// Startup the container before this point, using @Container or just container.start().
// That should run all your scripts and wait for the waiter
// Get the DockerClient used by the TestContainer library (you can also use your own if they every make that private).
final DockerClient dockerClient = customMSSqlContainer.getDockerClient();
// Commit docker container changes into new image
dockerClient.commitCmd(customMSSqlContainer.getContainerId())
.withRepository("myproject")
.withTag("db-ready")
.exec();
// Push new image. Logger is used for visual feedback.
dockerClient.pushImageCmd("myproject:db-ready")
.exec(new ResultCallback.Adapter<>() {
@Override
public void onNext(PushResponseItem object) {
log.info(object.toString()); // just log the push to the repo
}
}).awaitCompletion();
}
这种方法的潜在缺陷
docker commit 不会保存任何已保存到卷中的内容。
这是一个问题,因为大多数数据库图像实际上会创建一个卷。我看不到你的 Dockerfile,但请确保你保存的所有数据都没有保存到卷中!
阅读更多
我最近在 JFokus 会议上与 TestContainers 核心团队的一个人在我的房间里简短地谈到了这个问题:https://youtu.be/pxxMnvu52K8?t=1922
关于此主题的博客 post 即将完成,将在发布时更新此答案
我正在使用带有 Spring-Boot 的 Tescontainer 开发一些测试用例,以便启动 MS-SQL dockerized 数据库。这是一个巨大的数据库,需要大约 40 分钟才能在 docker 运行 进程中恢复。
我处理这张图片的步骤是:
- 使用模式和数据脚本将其标记为“db”构建 Dockerfile。
- 运行 容器并等待大约 40 分钟以恢复数据库。
- 提交带有“db-ready”标签的容器。
我期望的行为是测试用例尝试 运行 来自“db-ready”图像的 cointainer,如果失败,则直接从 Dockerfile 构建图像。我试过的代码看起来像:
public static CustomMSSqlContainer getInstance() {
if (container == null) {
try {
container = new CustomMSSqlContainer("myproject:db-ready");
}catch(Exception ex) {
container = new CustomMSSqlContainer(new ImageFromDockerfile().withFileFromClasspath("Dockerfile", "docker/Dockerfile")
.withFileFromClasspath("schema.sql", "docker/schema.sql")
.withFileFromClasspath("entrypoint.sh", "docker/entrypoint.sh")
.withFileFromClasspath("data.sql", "docker/data.sql")
.withFileFromClasspath("data-init.sql", "docker/data-init.sql")
.withFileFromClasspath("start.sh", "docker/start.sh"));
}
container.waitingFor(Wait.forLogMessage("Database ready\n", 1)
.withStartupTimeout(Duration.ofHours(1)))
.withExposedPorts(1433);
}
return (CustomMSSqlContainer)container;
}
当然,这段代码并不像我预期的那样工作。
有什么建议吗?
我们是如何解决这个问题的
我们这样做的方法是仅在 Main/Dev 分支 上构建自定义图像。这样:
- 我们不需要 try-catch;
- 我们只在实际需要时构建一个新容器(在合并请求批准更改并合并到主分支之后);
- 此容器的构建仅在 CI 管道上完成(因此人们不必也不能随机推送到容器注册表)
这是一个使用 JUnit 测试的示例(在此示例中禁用,但您可以使用 Spring 配置文件来启用它):
@Test
@Disabled("Should be run only with certain profiles ;)")
public void pushNewImage() throws InterruptedException {
// Startup the container before this point, using @Container or just container.start().
// That should run all your scripts and wait for the waiter
// Get the DockerClient used by the TestContainer library (you can also use your own if they every make that private).
final DockerClient dockerClient = customMSSqlContainer.getDockerClient();
// Commit docker container changes into new image
dockerClient.commitCmd(customMSSqlContainer.getContainerId())
.withRepository("myproject")
.withTag("db-ready")
.exec();
// Push new image. Logger is used for visual feedback.
dockerClient.pushImageCmd("myproject:db-ready")
.exec(new ResultCallback.Adapter<>() {
@Override
public void onNext(PushResponseItem object) {
log.info(object.toString()); // just log the push to the repo
}
}).awaitCompletion();
}
这种方法的潜在缺陷
docker commit 不会保存任何已保存到卷中的内容。 这是一个问题,因为大多数数据库图像实际上会创建一个卷。我看不到你的 Dockerfile,但请确保你保存的所有数据都没有保存到卷中!
阅读更多
我最近在 JFokus 会议上与 TestContainers 核心团队的一个人在我的房间里简短地谈到了这个问题:https://youtu.be/pxxMnvu52K8?t=1922
关于此主题的博客 post 即将完成,将在发布时更新此答案