如何 运行 自定义 docker 图像 testContainer

How to run a custom docker image testContainer

我浏览了多个博客和官方文档,但无法解决我的问题。我正在使用 testContainers-scala 版本 0.38.1scala 版本 2.11.

我正在尝试使用 testContainer-scala 创建一个简单的测试,如下所示:

class MyServiceITSpec extends AnyFlatSpec with ForAllTestContainer {
  override val container = GenericContainer(dockerImage="my-service",
    exposedPorts = Seq(8080),
    env=(HashMap[String, String]("PARAM1" -> "value1", "PARAM2" -> "value2", "PARAM3" -> "value3")),
    waitStrategy = Wait.forHttp("/")
  )

  "GenericContainer" should "start my service and say Hello! Wassupp" in {
    assert(Source.fromInputStream(
      new URL(s"http://${container.containerIpAddress}:${container.mappedPort(8080)}/").openConnection().getInputStream
    ).mkString.contains("Hello! Wassupp"))
  }
}

根据以上片段,我的理解是这样的(如有错误请指正):

  1. 端口 8155 由 docker 容器公开,并且将分配一个针对相同端口的随机主机端口。
  2. 我们可以获得分配的端口 container.mappedPort

这里我想断言http://localhost:mappedPort/return您好!瓦苏普.

但是,我收到以下错误:

Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
  at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:498)
  at org.testcontainers.containers.GenericContainer.lambda$doStart[=13=](GenericContainer.java:325)
  at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
  ... 18 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Timed out waiting for URL to be accessible (http://localhost:32869/ should return HTTP 200)
  at org.testcontainers.containers.wait.strategy.HttpWaitStrategy.waitUntilReady(HttpWaitStrategy.java:214)
  at org.testcontainers.containers.wait.strategy.AbstractWaitStrategy.waitUntilReady(AbstractWaitStrategy.java:35)
  at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:890)
  at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:441)
  ... 20 more

相同的图像运行良好:

docker run -p 8081:8080 -e PARAM1=value1 -e PARAM2=value2 -e PARAM3=VALUE3 my-service

所以在处理错误之后,我发现了我的问题。这与请求中缺少所需的 Request Headers 有关。我正在为 运行 遇到类似问题的任何人添加参考代码。

import com.dimafeng.testcontainers.{ForAllTestContainer, GenericContainer}
import org.scalatest.flatspec.AnyFlatSpec
import org.testcontainers.containers.wait.strategy.Wait

import scala.collection.immutable.HashMap
import scalaj.http.Http



    class MyServiceITSpec extends AnyFlatSpec with ForAllTestContainer {
      override val container = GenericContainer(dockerImage="my-service-img:tag12345",
        exposedPorts = Seq(8080),
        env=(HashMap[String, String]("PARAM1" -> "value1", "PARAM2" -> "value2")),
        waitStrategy = Wait.forHttp("/") // or "/health" based on ur implementation 
      )
    
      "My Service" should "successfully fetch the msg" in {
        assert(Http(s"http://${container.containerIpAddress}:${container.mappedPort(8080)}/products/product1")
          .header("HEADER1", "value1")
          .header("HEADER2", "value2")
          .asString.code==200)
      }
    
    }

经过大量阅读后我找到的一些解释:

  1. 您将 docker 应用程序公开的端口号指定为 exposedPorts
  2. TestContainers 然后将这个端口映射到一个随机端口(这是为了避免端口号冲突而设计的)。如果你要 运行 这个 docker 图像直接在你的机器上你会写:

docker run -p 8081:8080 -e PARAM1=value1 -e PARAM2=value2 my-service-img:tag12345

这里,你的暴露端口是8080映射端口是8081

  1. TestContainers 运行通过公开端口 8080 然后将其映射到随机端口来提供 docker 图像。映射的端口可以是container.mappedPort().

  2. 另一个需要注意的重要事项是等待策略。这告诉代码等待,除非 / 端点启动。这是您的应用程序公开的一种健康检查。你可以有一个更好的端点——比如 /health。默认情况下,它会等待 60 秒 以使此端点变为活动状态。 Post 它无论如何都会 运行 测试,如果到那时应用程序还没有启动,它会导致错误。我不确定如何覆盖默认超时,但我认为应该有办法做到这一点。

  3. 最后,我正在使用 scalaj.http.Http 发出 HTTP 请求(这是一个非常容易使用的请求 - 你可以)。