There are 2 libraries for Docker Engine Java API listed in the official reference page https://docs.docker.com/engine/api/sdks/.
This post is about how to use docker-client library to control docker engine in Java.
1. Running RabbitMQ on Container with Java Docker-Client API
You can find RabbitMQ docker image here.
Let's say, you want to start RabbitMQ service on docker container with the following command.
docker run -d --hostname rabbitmq rabbitmq:3.6
Then, define the following function in your java code and call it.
public static ContainerInfo start_rabbitmq_container(DockerClient docker_client, String rabbitmq_image, String rabbitmq_hostname) throws Exception {
final ContainerConfig containerConfig = ContainerConfig.builder()
.hostname(rabbitmq_hostname) // For option --hostname rabbitmq: String rabbitmq_hostname = "rabbitmq"
.image(rabbitmq_image) // Set docker image: String rabbitmq_image = "rabbitmq:3.6"
.build();
final ContainerCreation creation = docker_client.createContainer(containerConfig);
final String id = creation.id();
// Start container
docker_client.startContainer(id);
// Get rabbitmq container name
final ContainerInfo info = docker_client.inspectContainer(id);
return info;
}
This function returns Containerinfo info
. The variable info
contains information related to the container such as container_name, container_id and container_ip. So, in my case, as rabbitmq container's ip and name are used later, those values are retrieved like below.
final String rabbitmq_name = rabbitmq_container_info.name();
final String rabbitmq_ip = rabbitmq_container_info.networkSettings().ipAddress();
I couldn't find the way to name a new container a specific name (usually you can simply do this with "--name" option). As a result, if you want to use a container name in other operations, you need to extract container name, which is assigned by docker engine randomly, from info.name()
as shown above.
In addition, note that Containerinfo info.name()
returns container's name with /
on its head (I don't know why). (For example, it returns /container_name
instead of container_name
). Therefore, you should format the string by container_name.replace("/","")
.
2. Running PostgreSQL on Container with Java Docker-Client API
You can find PostgreSQL docker image here.
Let's say, you want to start PostgreSQL service on docker container with the following command.
docker run -it -d -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password -e POSTGRES_DB=test_db postgres:9.6.3
Then, define the following function in your java code. When starting postgres on a cotainer, you should export user/password as environment variables by setting ContainerConfig.builder().env("ENVIRONMENT_VARIABLE=VALUE")
like below.
public static String start_postgres_container(DockerClient docker_client, String postgres_image, String POSTGRES_USER, String POSTGRES_PASSWORD, String POSTGRES_DB) throws Exception {
String env_POSTGRES_USER = String.format("POSTGRES_USER=%s", POSTGRES_USER);
String env_POSTGRES_PASSWORD = String.format("POSTGRES_PASSWORD=%s", POSTGRES_PASSWORD);
String env_POSTGRES_DB = String.format("POSTGRES_DB=%s", POSTGRES_DB);
final ContainerConfig containerConfig = ContainerConfig.builder()
.env(env_POSTGRES_USER, env_POSTGRES_PASSWORD, env_POSTGRES_DB)
.image(postgres_image)
.build();
final ContainerCreation creation = docker_client.createContainer(containerConfig);
final String id = creation.id();
// Start container
docker_client.startContainer(id);
// Get postgres container name
final ContainerInfo info = docker_client.inspectContainer(id);
return info.name();
}
3. Linking Containers using Java Docker-Client API
Now you have started RabbitMQ service and PostgreSQL on containers. Next, you may want to link a new container with RabbitMQ and PostgreSQL containers. In that case, for example. you can execute the following command.
docker run -it --link rabbitmq:rabbitmq --link postgres_test:postgres image_to_run:tag java -jar /jar/file/to/execute
You can do the same with the following function in Java.
public static String start_xio_log_collector(DockerClient docker_client, String image_to_run, String path_to_jar, String formatted_postgres_name, String formatted_rabbitmq_name) throws Exception {
String link_postgres = String.format("%s:postgres", formatted_postgres_name); //configure --link option
String link_rabbitmq = String.format("%s:rabbitmq", formatted_rabbitmq_name); //configure --link option
final HostConfig hostConfig = HostConfig.builder()
.links(link_postgres, link_rabbitmq)
.build();
// Create container with exposed ports
final ContainerConfig containerConfig = ContainerConfig.builder()
.hostConfig(hostConfig)
.image(image_to_run)
.cmd("java", "-jar", path_to_jar)
.build();
final ContainerCreation creation = docker_client.createContainer(containerConfig);
final String id = creation.id();
// Start container
docker_client.startContainer(id);
return id;
}
Here, you can configure --link
operation by setting like HostConfig.builder().links(container1_to_link, container2_to_link)
.
4. Remove Containers after All Jobs Completed
Finally, in most cases, you may want to remove all containers after they finish all their jobs. Then, just use the following code.
docker.killContainer(container_name or container_id);
docker.removeContainer(container_name or container_id);
Note that, if you need to keep PostgreSQL Database, don't remove PostgreSQL container as containers are stateless and lose all data if you remove them.