Johann is a simple Java library that communicates with docker-compose CLI.
Just add Johann as a maven/gradle dependency and start using it. See Example usage for more information.
Maven dependency:
<dependency>
<groupId>io.brachu</groupId>
<artifactId>johann</artifactId>
<version>1.1.0</version>
</dependency>Gradle dependency:
compile 'io.brachu:johann:1.1.0'- JDK8+ environment
- Docker Engine 17.06+
- Docker Compose 1.18+
DockerCompose compose = DockerCompose.builder().classpath().build();DockerCompose compose = DockerCompose.builder().classpath("/custom-compose-file.yml").build();DockerCompose compose = DockerCompose.builder().classpath("/path/to/docker-compose.yml").build();DockerCompose compose = DockerCompose.builder().absolute("/path/to/docker-compose.yml").build();compose.up();
compose.waitForCluster(1, TimeUnit.MINUTES);Calling up method is equivalent to executing docker-compose up -d command.
waitForCluster method waits for all containers within a cluster to be either healthy or, if they have no health check, running.
For most consistent results in integration tests, all your containers should implement health checks.
You can read more about container health checks here.
compose.down();Calling down method is equivalent to executing docker-compose down -v command.
You can customize behaviour of down method by supplying it with a DownConfig object.
DownConfig object has following properties:
| Property | CLI equivalent | default value |
|---|---|---|
removeImages |
--rmi |
NONE |
removeVolumes |
-v |
true |
removeOrphans |
--remove-orphans |
false |
timeoutSeconds |
-t |
10 |
Example usage:
DownConfig config = DownConfig.defaults().withRemoveVolumes(false);
compose.down(config);compose.kill();Calling kill method is equivalent to executing docker-compose kill command.
compose.stop("postgresql");compose.start("postgresql");
compose.waitForService("postgresql", 1, TimeUnit.MINUTES);You can stop and start multiple services at once by using varargs-flavoured stop & start methods. There are also stopAll & startAll methods
available that can stop and start all services defined in your docker-compose file.
// The order of services matters. Rabbitmq service will be stopped before postgresql.
compose.stop("rabbitmq", "postgresql");
// Postgresql will start before rabbitmq
compose.start("postgresql", "rabbitmq");compose.stopAll()
compose.startAll()DockerCompose compose = DockerCompose.builder()
.classpath()
.env("MY_ENV_VAR", "my value")
.env("ANOTHER_VAR", "another value")
.build();By default, Johann uses implicitly generated project name and passes it to docker-compose command via -p switch.
You can override this behaviour by passing your own project name to the builder:
DockerCompose compose = DockerCompose.builder()
.classpath()
.projectName("customProjectName")
.build();When running docker-compose up without -p switch, your compose cluster will be assigned a project name equal to the name of directory containing your
docker-compose.yml file. This may lead to problems when running multiple clusters at once. Johann tries to handle this case by always passing
a project name to docker-compose CLI. This project name can be given explicitly via builder pattern or can be generated implicitly.
The sources of implicit project name are given below, ordered by priority:
System.getProperty("maven.dockerCompose.project")(will be used if returned value is not blank)System.getenv("COMPOSE_PROJECT_NAME")(will be used if returned value is not blank)- Random ASCII string generator
Assuming following docker-compose.yml file:
version: '2.3'
services:
rabbitmq:
image: rabbitmq:3.6.10-alpine
ports:
- "5672"You can easily retrieve container's IP address for rabbitmq service:
String ip = compose.containerIp("rabbitmq");If a container is bound to multiple networks, you can pass the network name as a second argument to the ip method:
String ip = compose.containerIp("rabbitmq", "my_custom_network");Assuming following docker-compose.yml file:
version: '2.3'
services:
rabbitmq:
image: rabbitmq:3.6.10-alpine
ports:
- "5672"You can retrieve a host port bound to container's 5672 port by invoking Johann's port method:
ContainerPort containerPort = compose.port("rabbitmq", 5672);
int port = containerPort.getPort();You can even use ContainerPort::format method to create proper URL address with one-liner:
String url = compose.port("rabbitmq", 5672).format("tcp://$HOST:$PORT");Johann can connect to a remote Docker Engine if DOCKER_HOST environment variable is passed to the Java process that runs Johann.
DOCKER_TLS_VERIFY and DOCKER_CERT_PATH variables are also supported.
You can read more about these variables here.
Running tests located in this repository requires you to install docker and docker-compose on your local machine. Also, assuming you are running Linux distro,
user running the tests must be added to the docker group. Version requirements are posted at the top of this README.