Docker Container Operations with Docker-Client API for Java

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](https://hub.docker.com/_/rabbitmq/).
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](https://hub.docker.com/_/postgres/).
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.