aaronp / dockerenv

A utility for starting services in docker, typically to facilitate testing

Version Matrix

dockerenv

Build Status Maven Central Coverage Status Scaladoc

Dockerenv provides a handle on useful docker containers, typically for running tests against real services as opposed to having to mock.

See docs here

The gist is that we can easily spin up real services (databases, kafka clusters, etc) which we can then connect against.

e.g. Import docker env in your build like this:

libraryDependencies += "com.github.aaronp" %% "dockerenv" % "latest version" % "test" 

Then use it like this:

  println(step("Let's do some ETL! Starting Mysql...", 0))
  dockerenv.mysql().bracket {
    println(step("Mysql Started, Starting Kafka", 1))
    dockerenv.kafka().bracket {
      println(step("Kafka Started, Starting Mongo", 2))
      dockerenv.mongo().bracket {
        println(step("All up! Killing Mongo...", 3))
      }
      println(step("Mongo Down, Killing Kafka", 2))
    }
    println(step("Kafka Down, Killing Mysql", 1))
  }
  println(step("All done!", 0))

  // pretty-prints the message with the current 'docker ps' status
  private def step(msg: String, indent: Int): String = {
    val status      = dockerPS
    ...
  }

  def dockerPS: String = "docker ps".!!

The output for which is:

_____________________________________________________________________________________________________________________________
Let's do some ETL! Starting Mysql...
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

    ________________________________________________________________________________________________________________________________________________________________
    Mysql Started, Starting Kafka
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS                               NAMES
    39d16d02b95c        mysql:8.0.18        "docker-entrypoint.s…"   1 second ago        Up Less than a second   33060/tcp, 0.0.0.0:7777->3306/tcp   dockerenv-mysql
    
        __________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
        Kafka Started, Starting Mongo
        CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                  PORTS                                                                                                                      NAMES
        a6e9bea0393c        dockerenv-kafka:test   "supervisord -n"         1 second ago        Up Less than a second   0.0.0.0:2181->2181/tcp, 0.0.0.0:8083->8083/tcp, 0.0.0.0:9080->9080/tcp, 0.0.0.0:9092->9092/tcp, 0.0.0.0:29092->29092/tcp   test-kafka
        39d16d02b95c        mysql:8.0.18           "docker-entrypoint.s…"   2 seconds ago       Up 1 second             33060/tcp, 0.0.0.0:7777->3306/tcp                                                                                          dockerenv-mysql
        
            __________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
            All up! Killing Mongo...
            CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                  PORTS                                                                                                                      NAMES
            fef2d8c0662a        mongo:4.0              "docker-entrypoint.s…"   1 second ago        Up Less than a second   0.0.0.0:9010->27017/tcp                                                                                                    dockerenv-mongo
            a6e9bea0393c        dockerenv-kafka:test   "supervisord -n"         2 seconds ago       Up 1 second             0.0.0.0:2181->2181/tcp, 0.0.0.0:8083->8083/tcp, 0.0.0.0:9080->9080/tcp, 0.0.0.0:9092->9092/tcp, 0.0.0.0:29092->29092/tcp   test-kafka
            39d16d02b95c        mysql:8.0.18           "docker-entrypoint.s…"   3 seconds ago       Up 2 seconds            33060/tcp, 0.0.0.0:7777->3306/tcp                                                                                          dockerenv-mysql
            
        ______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
        Mongo Down, Killing Kafka
        CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                                                                                                      NAMES
        a6e9bea0393c        dockerenv-kafka:test   "supervisord -n"         3 seconds ago       Up 1 second         0.0.0.0:2181->2181/tcp, 0.0.0.0:8083->8083/tcp, 0.0.0.0:9080->9080/tcp, 0.0.0.0:9092->9092/tcp, 0.0.0.0:29092->29092/tcp   test-kafka
        39d16d02b95c        mysql:8.0.18           "docker-entrypoint.s…"   4 seconds ago       Up 3 seconds        33060/tcp, 0.0.0.0:7777->3306/tcp                                                                                          dockerenv-mysql
        
    ____________________________________________________________________________________________________________________________________________________________
    Kafka Down, Killing Postgres
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
    39d16d02b95c        mysql:8.0.18        "docker-entrypoint.s…"   6 seconds ago       Up 4 seconds        33060/tcp, 0.0.0.0:7777->3306/tcp   dockerenv-mysql
    
_____________________________________________________________________________________________________________________________
All done!
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

You can also depend on the test artifact to extend common base test classes:

libraryDependencies += "com.github.aaronp" %% "dockerenv" % "latest version" % "test" classifier "tests"

which gives you:

// the BaseXYZSpec classes ensure XYZ is started/stopped for your tests, and expose a 'dockerHandle' should you need to 
// stop the services for run more complex scenarios, like testing failover/retries  
class MyKafkaTest extends BaseKafkaSpec {

  "Kafka" should {
    "connect to a running kafka instance" in {

      isDockerRunning() shouldBe true
 
      val topic = "testTopic"

      // insert your code here which needs to do something with kafka (e.g. publish/consume some data)
      // here we just execute a script within the kafka container to demonstrate it's running by invoking 
      // 'kafka-topics.sh' script within the container via our listTopics.sh wrapper 
      val Success((0, listOutput)) = dockerHandle.runInScriptDir("listTopics.sh")
      listOutput should not be(empty)
    }
  }
}