Deploying Dropwizard on App Engine Flex
A few months ago we started working on a project which involved deploying Dropwizard on Google Cloud Platform. We researched the feasible solutions and App Engine was one of the top contenders. Below, I’ll walk you through our progress trying to deploy Dropwizard on App Engine, the issues we faced and the solutions we found for them.
App Engine & Dropwizard
App Engine provides a lot of great features out of the box, including load-balancing, versioning and more. It can scale up/down very effectively which is why we decided to use it with Dropwizard – our favourite REST API development framework. Deploying Dropwizard on App Engine wasn’t a straight forward process, here’s why.
War vs Jar
Dropwizard usually deploys as a jar
(Java Application Archive) file, which includes jetty
(the web server) inside it. In other words, it’s a fully functioning web server that includes the app. App Engine on the other hand expects the app to be deployed as a war
(Web Application Archive) file, and App Engine deploys the war
files on a web server.
This means we needed to turn the Dropwizard into a war
file and remove jetty from it. There are ways to deploy a Dropwizard as a war
file, all of them involve things that look like hacks. The options we found are Wizard in a box and WizToWar.
Servlet 2.5 vs Servlet 3
We followed the steps described above and tried deploying on App Engine, but we weren’t getting anywhere. It took us a while to figure out the reason behind the errors we were getting. We had to download the source code for Dropwziard and dig into it to figure out something we should’ve figured out way sooner:
- Dropwizard depends on Servlet API version 3 or higher.
- App Engine standard environment is still on Servlet API version 2.5 (you can read this 7 year old thread on that topic)
With all of that information we were able to say that:
It’s impossible to deploy Dropwizard on App Engine standard environment
Flexible Environment to Rescue
Around then is when we learned about App Engine Flexible Environments. It’s a new service provided by Google App Engine, still in beta. It allows developers to have access to all the features of App Engine, without being tied to the limitations that come along with it. It has 2 Java Runtime Environments available: Java 8 with Jetty 9.3 and Java 8 (without any web server).
The Java 8 environment was the best fit to what we needed and is what we’ll walk you through below. To be able to use it, we had to ask the Google Cloud Platform team to add us to the beta program, though I’ve heard they are going to release it to public later this quarter.
App Engine Flex – How to
You can clone the sample project from github so you have all the code in one place. It’s a simple hello world Dropwziard application with Gradle as the build tool.
To run the app locally you can use this command:
./gradlew run
Then visit the http://localhost:8080/
and you should see hello world – dropwizard app engine flex
Now that you can run it locally, let’s try deploying it on App Engine Flex.
Preparation
All the code you need for deployment to App Engine is in a folder called appengine
.
appengine --app.yaml --Dockerfile
As you can see the structure of that folder, there are only 2 files.
app.ayml
is where we define App Engine related variablesDockerfile
contains what App Engine needs to deploy and run our app.
app.yaml
You can use the app.yaml
file to configure your App Engine application. It has been used in App Engine standard environment as well. Here is a full reference you can use to get more familiar with it.
What we have in app.yaml
is very minimal:
runtime: custom env: flex service: hello-world
We are setting only 3 variables:
env: flex
means we are using the flexible environment, not the standard environmentruntime: custom
means we are using Java 8 runtime, with no Jetty.service: hello-world
is just giving a name to the service we are going to deploy this app under.
Dockerfile
This is one of the main differences of the flexible environment and the standard environment. The flexible environment is based on Google Compute Engine. The deployment is happening on the Compute Engine although we are getting the benefits of having an App Engine service. The Dockerfile
is how we define how our app should run on Compute Engine.
Let’s have a look at the Dockerfile
:
FROM gcr.io/google_appengine/openjdk8 VOLUME /tmp ADD app.jar app.jar ADD config.yaml config.yaml CMD
First of all, we are starting from gcr.io/google_appengine/openjdk8
. It’s base docker image which is specific to Java 8 Runtime of the App Engine Flex. Then we are adding app.jar
(our Dropwizard app) and config.yaml
(the configuration file). In the last command we are telling docker how to run our app: Run app.jar
with arguments server
and config.yaml
.
Jar vs ShadowJar
As we are going to run our Dropwizard app from a jar
file, that jar file has to have all the dependencies required to run the app. Gradle’s java plugin doesn’t do this by default, that’s why we are using shadow-jar
plugin.
To create a jar file with all the dependencies you can use this command:
./gradlew shadowJar
gcloud
gcloud is a tool that provides a command line interface for Google Cloud Platform. We are going to use it to deploy our app on App Engine Flexible environment.
Login
In order to be able to run commands on Google Cloud Platform using gcloud
, you need to first login. You can do that via
gcloud auth login
This will redirect you to your browser to login. One other option is to login with service accounts. It’s what we use on for continuous deployment. You can read more about that here: Activate a Service Account
Get ready to deploy
As you saw in Dockerfile
, you need to copy app.jar
and config.yaml
to the appengine
folder for the deployment to be able to run successfully. In our continuous integration we do that with a script, but here you can just copy those files.
Deploy
You have everything ready! Now you just need to initiate the deployment process. First you need to set the project you are going to deploy to, and then deploy it with a version number. If version number is empty, it will generate a version number using the date and time of deployment. You have to run this commands from inside the appengine
folder.
gcloud config set project my-dropwizard gcloud app deploy --version=1.0
Check Deployment
If everything goes well, you should have your Dropwizard app deployed and can look at it in the cloud. For that you can use this command:
gcloud app browse -s hello-world
You can also look at your app logs via
gcloud app logs read
Results
It took us a while to figure out the ins and outs of deploying Dropwizard on App Engine, but the Google Cloud Platform team was super helpful and responsive throughout the process. We learned a lot along the way but the most important thing was that it is possible to deploy the Dropwizard application on the App Engine Flexible environment.
I hope sharing this with you will save you a bit of time and make the process easier. If you have any issues, feel free to comment here and we’ll answer as soon as we can.
Good luck!
This was a lifesaver! Thanks a ton!
It is possible to do java8 directly without providing docker config. (It auto manages the docker config internally) However, if you want to send an argument to your executable or you have an exploded binary instead of a single fat (shadow) jar, then you have to choose the custom runtime.
Hi Suvodeep,
You are completely correct. Google Cloud has added Java 8 support on App Engine Standard Environment as well, which means now you have multiple options for using Java 8 on App Engine.