9 minutes read
Running Dropwizard Applications on Kubernetes
Dropwizard is a popular Java library for building RESTful web services. I am using this library for my user management application, Thunder, and it makes building the API much easier and more enjoyable. When it comes to deploying applications, Kubernetes is the new hot product. I wanted to run my Dropwizard application on Kubernetes, and decided to put together a guide for anyone else looking to do the same.
Building the Application
I will assume that if you’re reading this guide, you already have a Dropwizard project ready to deploy. If not, follow the getting started guide for v1.3.1 of Dropwizard. You can also check out my project, Thunder, for a working example that you can use. Just clone that repository to your computer using git.
Using Maven, build the application into a packaged jar that you can run anywhere.
$ mvn package
Create the Docker image
In order to run your application on Kubernetes, you need a Docker image with your application.
So, let’s build one! Create a new file named
Dockerfile in the base directory of your project
(i.e. next to your parent
pom.xml) and add the following content.
1 2 3 4 5 6 7 8 FROM openjdk:8-jre-alpine LABEL maintainer "YOUR NAME email@example.com" COPY ./application/target/application-*.jar application.jar EXPOSE 80 81 ENTRYPOINT ["java", "-jar", "/application.jar", "server", "/home/config/config.yaml"]
Let’s go through this file line by line. First, we specify what existing Docker image to build this
FROM. We are using the
openjdk:8-jre-alpine image since we are running our application using
Java 8. If you are using a different Java version,
check the available images. We use the Alpine flavor in order to
have a smaller Docker image.
Next, we define the maintainer
LABEL which provides your information. This line is optional.
Then, in order to get your application into the Docker image, we need to
COPY it in. This line copies
the jar that we built into the image. If your jar file is named differently, you will need to modify this
After copying the application, we have to
EXPOSE the ports that our application will be listening on. If you
set up your Dropwizard configuration to listen on different ports, change those here.
Finally, we define the
ENTRYPOINT for running the image. This is the command to start your
Dropwizard application. Notice that we reference
config.yaml, which does not yet exist in our image.
We will take care of adding the configuration file when we deploy the application. We don’t want to bake it
into the image because our configuration could change at any time.
Now, let’s build our image. Make sure you have Docker installed. If you don’t, go here to install. Run the following command to tag and build your image.
$ sudo docker build -t yourname/application:test .
Feel free to change the tag to anything else. You should replace
yourname with your Docker Hub username,
application with the name of your application.
Now we will push our image to Docker Hub. If you haven’t yet, create an account on Docker Hub. You can also use a private Docker registry, but I will not cover that in this post. Once you create an account, login on the command line.
$ sudo docker login
After entering your credentials, you’re set to push your image!
$ sudo docker push yourname/application:test
Check your Docker Hub account to verify that your application was pushed! Now that we have our application packed into a Docker image, we can run it using Kubernetes.
Create a Kubernetes Cluster
Kubernetes is growing quickly in popularity, and there are many great guides on how to get started. If you are not familiar with Kubernetes (or K8s), I recommend that you first learn about it and make sure that you are comfortable with the terminology.
To create a cluster, we can use minikube to
run one locally. First, we need to install minikube.
Minikube requires a hypervisor (i.e. VirtualBox, Hyper-V, or VMWare Fusion) to be installed, so make sure that
you follow those directions. Install the hypervisor, then install the command line tools
kubectl, then install
minikube. The instructions differ based on what OS you are on, so please follow the linked instructions.
Once everything is installed, start the cluster.
$ minikube start
If you do not wish to use minikube locally, and want to jump straight into running in the cloud, follow guides for creating a K8s cluster on one of the following cloud providers:
Create Configuration File
Kubernetes supports ConfigMaps that provide a way to inject your container with configuration data. This is the approach we will use to provide the Dropwizard configuration file to our application.
First, create a new file called
application-config.yaml, and add the following content.
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: ConfigMap metadata: name: application-config data: config.yaml: | server: applicationConnectors: - type: http port: 80 adminConnectors: - type: http port: 81
This is a YAML file that defines a Kubernetes resource. The
apiVersion tells Kubernetes what version
of the API to use when processing the file. The
kind of resource that we will create with this file
is a ConfigMap. In the
metadata, we define the name of the ConfigMap, and in the
data, we define
what the configuration actually is. In this case, we want the configuration to be a file called
config.yaml. Inside that file, we want to define our Dropwizard configuration. Put your Dropwizard
YAML configuration here. For this example, I have just defined the
server configuration for Dropwizard,
but you can see here
for a full example based on my Thunder application.
Now that we have the file, we can create the ConfigMap in our running Kubernetes cluster. Make sure that
you are connected to your cluster using
kubectl, and then run the command.
$ kubectl apply -f application-config.yaml
You can then verify that it was created by running the get command.
$ kubectl get configmap
You should see the name of your ConfigMap as the output.
Running the Application
Now, we’re ready to deploy our application. Define another file called
and add the following content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 apiVersion: apps/v1beta1 kind: Deployment metadata: name: application spec: replicas: 2 template: metadata: labels: app: application spec: containers: - name: application image: yourname/application:test imagePullPolicy: Always ports: - containerPort: 80 - containerPort: 81 volumeMounts: - name: config-volume mountPath: /home/config livenessProbe: httpGet: path: /healthcheck port: 81 initialDelaySeconds: 10 timeoutSeconds: 1 readinessProbe: httpGet: path: /healthcheck port: 81 initialDelaySeconds: 10 timeoutSeconds: 1 volumes: - name: config-volume configMap: name: application-config --- apiVersion: v1 kind: Service metadata: name: application spec: type: LoadBalancer ports: - port: 80 targetPort: 80 selector: app: application
This is where everything comes together. We first define a Kubernetes Deployment, which is the main application.
spec, we define that we want 2
replicas of the application running at all times. Then, inside
template spec, we define the containers we want to run and the volumes that we want to create. For the
containers, we only want to run one container - the Docker image that we built earlier. We define the image
tag from earlier under the
image property. We also have to tell Kubernetes that we have a few open
on the container,
81. We also define a
volumeMount that mounts a volume into the container.
This volume will contain our Dropwizard configuration file, and so we specify the path as
that is the path we assumed the configuration would exist in our
ENTRYPOINT command in our
Finally, we define a
livenessProbe that Kubernetes will probe to ensure our application is alive (and replace
it if it is dead), and a
readinessProbe that Kubernetes will probe before starting to serve traffic to that
Pod. In both cases, we tell Kubernetes to probe the Dropwizard
/healthcheck endpoint on the admin port,
Lastly, we define a volume called
config-volume that holds the ConfigMap we created earlier. As mentioned in the paragraph above, we mount this volume into our container so that our application has access to the data.
The second resource that is defined is a Service. This acts as a load balancer, and Kubernetes will manage the
relationship between our multiple running containers and the load balancer to spread traffic between them.
We can specify the open ports on the load balancer, and what the
targetPort should be (the port to proxy
the traffic to on the container). The
selector defines which set of containers to balance across, so we
app: application label that we defined in the Deployment.
Note that the Service type
LoadBalancer only works in the context of clusters running on cloud providers. If
we are using minikube, we should use the
NodePort type to expose the service on the IP of the running Node.
Let’s create the Deployment and Service in one go:
$ kubectl apply -f application-deployment.yaml
And your application is up! If you are using the LoadBalancer, wait a few minutes and then run the following command to get the external IP of the load balancer.
$ kubectl get svc application
Once you have the external IP, run a test using
curl. For example, if your application has a
$ curl 220.127.116.11/hello
If everything worked, you will get your HTTP response back! If it doesn’t work, you can troubleshoot by checking to make sure your containers are running:
$ kubectl get deployment application
If they are not running, you should check the Dropwizard logs to see what went wrong. Get the name of one of your Pods:
$ kubectl get pods
Find one of the
application-* Pods (for example, application-6cffc7bb7-gjg5q), and then run:
$ kubectl logs application-6cffc7bb7-gjg5q
This will show you all of the logs output by Dropwizard.
Now you’ve learned how to containerize your Dropwizard application, keep your configuration separate, and create a Kubernetes ConfigMap and Deployment for your application. Deploying your Dropwizard application in this way will allow you to iterate and deploy quickly and effortlessly. Enjoy your containerized Dropwizard application, and reach out (firstname.lastname@example.org) or leave a comment if you have any problems or questions.