Using Docker to Deploy a Containerized Java Web App

DZone 's Guide to

Using Docker to Deploy a Containerized Java Web App

Docker can be used to create a familiar environment for devs to work on. Using a simple API, you can build a Docker image and deploy it to suit your needs.

· Java Zone ·
Free Resource

Not too long ago I wrote about containerizing a Node.js RESTful API and Couchbase Server to demonstrate how easy it is to deploy web applications in a quick and reliable fashion. In that guide, we created a simple API, built a Docker image from it, deployed it as a container, and deployed Couchbase as a container. However, I understand that not everyone is familiar with Node.js.

Here we’re going to build a simple Java RESTful API using Spring Boot, create a Docker image from it, and deploy it as a container with Couchbase. This will create a familiar environment for Java developers.

This tutorial requires that you have a Docker installed and configured on your machine. With Docker, we’ll be creating custom Docker images and deploying them as containers.

Create a Custom Docker Image for Couchbase Server

Let’s start with creating a custom Docker image for Couchbase Server. While an official Couchbase image exists, it isn’t automatically provisioned when deployed. Our custom image will automatically provision itself upon deployment as a container.

Somewhere on your computer create a directory with a Dockerfile file and configure.sh file in it. The Dockerfile file will be the blueprint for our image and the configure.sh file will be the provisioning script that is run when the container is deployed.

Open the configure.sh file and include the following:

set -m

/entrypoint.sh couchbase-server &

sleep 15

curl -v -X POST -d memoryQuota=512 -d indexMemoryQuota=512

curl -v -d services=kv%2cn1ql%2Cindex




sleep 15


fg 1

Couchbase can be configured through HTTP after being deployed. Our configuration script will specify instance resources, administrative credentials, a Bucket, and a primary index. You’ll notice that a variety of variables are used such as $COUCHBASE_ADMINISTRATIVE_USERNAME and $COUCHBASE_BUCKET. These can be passed in at runtime preventing us from having to hard-code sensitive information.

More information on provisioning a Couchbase container via HTTP can be seen in a previous article that I wrote on the topic.

With the provisioning script complete, we have to finish the Dockerfile file. Open it and include the following:

FROM couchbase

COPY configure.sh /opt/couchbase

CMD ["/opt/couchbase/configure.sh"]

The custom Docker image will use the official Docker image as the base, copy our provisioning script during the build process, and execute it at runtime.

To build the custom image for Couchbase, execute the following:

docker build -t couchbase-custom /path/to/directory/with/dockerfile

In the above command, couchbase-custom is the image name and it is built from the path that contains the Dockerfile file.

Developing a Spring Boot RESTful API with Java

Before we can containerize our Java application we have to build it. Because we are using Spring Boot, we need to download a starter project. This can easily be done from the Spring Initializr website.

For this project, I’m using com.couchbase as my group and docker as my artifact. I also prefer Gradle, so I’m using that instead of Maven.

Extract the downloaded project, and open the project’s src/main/resources/application.properties file. In this file include the following:


In the above snippet, we are assuming our host instance is called couchbase and it has a passwordless Bucket called default. If you were testing locally, the host would probably be localhost instead. In any case, all these properties are going to be defined at container runtime through environment variables.

Now open the project’s src/main/java/com/couchbase/DockerApplication.java file. Here we’re going to load our properties and define our endpoints. Open this file and include the following Java code:

package com.couchbase;

import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.query.*;
import com.couchbase.client.java.query.consistency.ScanConsistency;
import com.couchbase.client.java.document.json.JsonObject;
import com.couchbase.client.java.document.JsonDocument;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.*;
import org.springframework.context.annotation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class DockerApplication {

    private String hostname;

    private String bucket;

    private String password;

    public @Bean
    Cluster cluster() {
        return CouchbaseCluster.create(hostname);

    public @Bean
    Bucket bucket() {
        return cluster().openBucket(bucket, password);

    @RequestMapping(value="/", method= RequestMethod.GET)
    public String root() {
        return "Try visiting the `/get` or `/save` endpoints";

    @RequestMapping(value="/get", method= RequestMethod.GET)
    public Object get() {
        String query = "SELECT `" + bucket().name() + "`.* FROM `" + bucket().name() + "`";
        return bucket().async().query(N1qlQuery.simple(query, N1qlParams.build().consistency(ScanConsistency.REQUEST_PLUS)))
                .map(result -> result.value().toMap())
                .timeout(10, TimeUnit.SECONDS)

    @RequestMapping(value="/save", method=RequestMethod.POST)
    public Object save(@RequestBody String json) {
        JsonObject jsonData = JsonObject.fromJson(json);
        JsonDocument document = JsonDocument.create(UUID.randomUUID().toString(), jsonData);
        return new ResponseEntity<String>(json, HttpStatus.OK);

public static void main(String[] args) {
SpringApplication.run(DockerApplication.class, args);

Not too much is happening in the above. Much of it is boilerplate code and import statements. Because the goal of this article isn’t in regards to using Java with Couchbase, I won’t explain each part of the code. Instead know that it has three endpoints, one of which will get all documents in the Bucket and one of which will save new documents to Couchbase.

If you’re using Gradle like I am, you need to change the build.gradle file. It needs to have a task created and dependencies added. Your build.gradle file should look something like this:

buildscript {
    ext {
        springBootVersion = '1.5.2.RELEASE'
    repositories {
    dependencies {

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {

dependencies {

task(run, dependsOn: 'classes', type: JavaExec) {
    main = 'com.couchbase.DockerApplication'
    classpath = sourceSets.main.runtimeClasspath

To build the application, execute the following:

gradle build -x test

Now you’ll have a JAR file to be used in our Docker image.

Build a Custom Docker Image for the Spring Boot Application

Building a custom image will require that we have a Dockerfile file in place. At the base of your Java project, add a Dockerfile file and include the following:

FROM openjdk:8

COPY ./build/libs/java-project-0.0.1-SNAPSHOT.jar spring-boot.jar

CMD java -jar spring-boot.jar

In the above snippet, we’re using the official OpenJDK image as our base and we’re copying our JAR into the image at build time. At deployment, the JAR is executed.

To build this image, execute the following:

docker build -t spring-boot-custom /path/to/directory/with/dockerfile

The above command should look familiar. We’re creating a spring-boot-custom image using the blueprint found in the directory of our Dockerfile file.

For more information on creating custom Docker images, you can visit a previous article I wrote called, Build a Custom Docker Image for Your Containerized Web Application.

Deploying the Couchbase and the Spring Boot Images as Containers

There are a few options when it comes to deploying our images. We can use a Compose file or deploy them as vanilla containers. I find Compose to be a cleaner approach so we’ll use that.

Somewhere on your computer create a docker-compose.yml file and include the following:

version: '2'

        image: couchbase-custom
            - 8091:8091
            - 8092:8092
            - 8093:8093
            - COUCHBASE_BUCKET=default

        image: spring-boot-custom
            - 8080:8080
            - COUCHBASE_HOST=couchbase
            - COUCHBASE_BUCKET=default
        restart: always

In the above file, we are defining the custom images that we built and we are doing port mapping to the host machine. What is particularly interesting is the environment options. These match the variables that we have in our application.properties and configure.sh files.

To deploy our containers with Compose, execute the following:

docker-compose run -d --service-ports --name couchbase couchbase
docker-compose run -d --service-ports --name spring-boot spring-boot

Something to note about the above commands. Couchbase does not deploy instantly. You’ll need to wait until it is completely launched before you deploy the Java application. After both applications are launched, check them out by navigating to the Java application in your web browser.


You just saw how to create custom Docker images for a Spring Boot application and Couchbase Server. After deploying each as containers, they will be able to communicate to each other, which is incredibly convenient for maintenance.

couchbase server, docker containers, java, restful api, tutorial

Published at DZone with permission of Nic Raboy , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}