Skip to content

j5ik2o/docker-controller-scala

This branch is up to date with main.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

b0a0dbe · Mar 26, 2025
Mar 26, 2025
Aug 21, 2023
Aug 9, 2022
Aug 9, 2022
Sep 25, 2023
Jul 12, 2021
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Aug 9, 2022
Jul 5, 2024
Mar 18, 2022
Jul 24, 2023
Jun 14, 2024
Apr 9, 2021
Sep 25, 2023
Jul 5, 2024
Apr 12, 2021
Oct 19, 2023
Apr 13, 2021

Repository files navigation

docker-controller-scala

Actions Status: CI Maven Central Renovate License Tokei FOSSA Status

This library provides an easy and simple way to handle Docker Container or Docker Compose on ScalaTest, based on docker-java. The implementation of this library is thin, and if you know docker-java, your learning cost will be negligible.

M1 Macs also be supported.

Installation

Add the following to your sbt build (2.12.x, 2.13.x, 3.0.x):

val version = "..."

libraryDependencies += Seq(
  "com.github.j5ik2o" %% "docker-controller-scala-core" % version,
  "com.github.j5ik2o" %% "docker-controller-scala-scalatest" % version, // for scalatest
  // RDB
  "com.github.j5ik2o" %% "docker-controller-scala-mysql" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-postgresql" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-flyway" % version, // optional
  // NoSQL
  "com.github.j5ik2o" %% "docker-controller-scala-memcached" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-redis" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-elasticsearch" % version, // optional
  // Kafka
  "com.github.j5ik2o" %% "docker-controller-scala-zookeeper" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-kafka" % version, // optional
  // AWS Services
  "com.github.j5ik2o" %% "docker-controller-scala-dynamodb-local" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-minio" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-localstack" % version, // optional
  "com.github.j5ik2o" %% "docker-controller-scala-elasticmq" % version, // optional
)

In most cases, you can just select the scalatest module and the module you need.

libraryDependencies += Seq(
  "com.github.j5ik2o" %% "docker-controller-scala-scalatest" % version,
  "com.github.j5ik2o" %% "docker-controller-scala-mysql" % version,
)

Usage

DockerController that the thin wrapper for docker-java controls Docker Image and Docker Container for testing.

How to test with preset DockerController

The DockerController for the corresponding preset is as follows. Please see the corresponding **Spec for specific usage.

Use Flyway Migrate Command on MySQL/PostgreSQL

If you'd like to use flyway module, you can use docker-controller-scala-flyway.

libraryDependencies += Seq(
  "com.github.j5ik2o" %% "docker-controller-scala-scalatest" % version,
  "com.github.j5ik2o" %% "docker-controller-scala-mysql" % version,
  "com.github.j5ik2o" %% "docker-controller-scala-flyway" % version, // for flyway
)

Mix-in FlywaySpecSupport then, put the sql files in src/resources/flyway(src/resources/** can be set to any string.), run flywayContext.flyway.migrate() in afterStartContainers method.

How to test with DockerController your customized

To launch a docker container for testing

// In ScalaTest, please mix-in DockerControllerSpecSupport.
class NginxSpec extends AnyFreeSpec with DockerControllerSpecSupport {
  
  // choose whether to create and destroy containers per test class (ForAllTest) or per test (ForEachTest).
  override def createRemoveLifecycle: DockerContainerCreateRemoveLifecycle.Value =
    DockerContainerCreateRemoveLifecycle.ForEachTest

  // choose whether to start and stop containers per test class (ForAllTest) or per test (ForEachTest).
  override def startStopLifecycle: DockerContainerStartStopLifecycle.Value =
    DockerContainerStartStopLifecycle.ForEachTest
    
  val nginx: DockerController = DockerController(dockerClient)(
    imageName = "nginx",
    tag = Some("latest")
  ).configureCreateContainerCmd { cmd =>
    // if customize the container generation, please do the following.
    // In this example, a random host port is specified.
    val hostPort: Int              = temporaryServerPort()
    val containerPort: ExposedPort = ExposedPort.tcp(80)
    val portBinding: Ports         = new Ports()
    portBinding.bind(containerPort, Ports.Binding.bindPort(hostPort))
    logger.debug(s"hostPort = $hostPort, containerPort = $containerPort")
    cmd
      .withExposedPorts(containerPort)
      .withHostConfig(newHostConfig().withPortBindings(portBinding))
  }

  // Specify DockerControllers to be launched.
  override protected val dockerControllers: Vector[DockerController] = {
    Vector(nginx)
  }

  // Set the condition to wait for the container to be started.
  override protected val waitPredicatesSettings: Map[DockerController, WaitPredicateSetting] =
    Map(
      nginx -> WaitPredicateSetting(
        Duration.Inf,
        WaitPredicates.forLogMessageContained("Configuration complete; ready for start up")
      )
    )

  "nginx" - {
    "run-1" in {
      val hostPort = nginx.inspectContainer().getNetworkSettings.bindingHostPort(ExposedPort.tcp(80)).get
      val url      = new URL(s"http://$dockerHost:$hostPort")
      HttpRequestUtil.wget(url)
    }
    "run-2" in {
      val hostPort = nginx.inspectContainer().getNetworkSettings.bindingHostPort(ExposedPort.tcp(80)).get
      val url      = new URL(s"http://$dockerHost:$hostPort")
      HttpRequestUtil.wget(url)
    }
  }
}

How to use Docker Compose

  • Place the docker-compose.yml.ftl(ftl is Freemarker template) in src/test/resources. docker-compose.yml.ftl can be renamed to anything you want.
  • The variables in the ftl can be freely determined.
version: '3'
services:
  nginx:
    image: nginx
    ports:
      - ${nginxHostPort}:80
  • Use DockerComposeController, which is a subtype of DockerController. Other than this, it is the same as the test method above.
  • Pass the context containing the values of the variables to be used in the FTL to the constructor of DockerComposeController.
class NginxSpec extends AnyFreeSpec with DockerControllerSpecSupport {
// ...
  val buildDir: File                = ResourceUtil.getBuildDir(getClass)
  val dockerComposeWorkingDir: File = new File(buildDir, "docker-compose")
  val dockerController = DockerComposeController(dockerClient)(
    dockerComposeWorkingDir,
    "docker-compose.yml.ftl",
    Map("nginxHostPort" -> hostPort.toString)
  )

  override val dockerControllers: Vector[DockerController] = {
    Vector(dockerController)
  }
// ...
}     

License

FOSSA Status