How to Deploy a Java Application to Google Compute Engine

Thu, Feb 18, 2016



The following walkthrough is a short example of how very simple scripting can bootstrap development on Google Compute Engine.

Source

All the source code for this example can be found here on github

Prerequisites

Make a java app

for this example we’re going to create a simple spring boot app

Download start-spring.sh to your workspace directory and chmod 775.

Setup a sample project with

  $ start-spring.sh gcedeploy web,actuator
  $ cd gcedeploy
  $ mvn spring-boot:run

Great now that the template works lets be sure we can run it with just java. First add a root context so the app actually returns something

Open src/main/java/com/demo/gcedeploy/GcedeployApp.java and update it to the following

package com.demo.gcedeploy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;


@SpringBootApplication
@RestController
public class GcedeployApp {

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

	@RequestMapping("/")
  public String hello(){
  	return "hello";
  }
}

Open src/main/resources/application.properties and update it to the following to have our server run on port 80

server.port = 80

Package it up

  $ mvn install

And run it

  $ java -jar ./target/gcedeploy-0.0.1-SNAPSHOT.jar

you should see your app running at http://localhost

Deploy scripts

This next part is really the point of this demo. Here we’re going to do two things. First we need a compute image with java installed so we can run our app. In a production setting you’ll probably use a pre baked image, but here we’ll just use a startup script to install everything

Create an install.sh file that we’ll sed to the new vm and have it execute on startup

It should look like this. NOTE you’ll need to change the BUCKET_NAME var to something just for your use.

#! /bin/bash

## This startup script runs ON the compute vm

BUCKET_NAME=your-unique-bucket-name
JAR_NAME=gcedeploy-0.0.1-SNAPSHOT.jar

sudo su -

echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list

echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
apt-get update

echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
apt-get install oracle-java8-installer -y

mkdir /opt/gcedeploy

gsutil cp gs://${BUCKET_NAME}/${JAR_NAME} /opt/gcedeploy/${JAR_NAME}
java -jar /opt/gcedeploy/${JAR_NAME} &
exit

So whats going on here? Most of this is just about downloading oracle java 8

The last 4 lines are the key points. We’re copying our jar file from google storage onto this server and running it.

But wait how did the jar get to google storage anyway?

This next script has the fun google bits in it to take care of all that for you

Create a start.sh an add the following. NOTE: Again update the first to variables to the same bucket name you used above

#! /bin/bash

BUCKET_NAME=your-unique-bucket-name

JAR_NAME=gcedeploy-0.0.1-SNAPSHOT.jar
VM_NAME=gcedeploy

gsutil mb gs://${BUCKET_NAME}
gsutil cp ./target/${JAR_NAME} gs://${BUCKET_NAME}/${JAR_NAME}

gcloud compute firewall-rules create ${VM_NAME}-www --allow tcp:80 --target-tags ${VM_NAME}

gcloud compute instances create ${VM_NAME} \
  --tags ${VM_NAME} \
  --zone us-central1-a  --machine-type n1-standard-1 \
  --metadata-from-file startup-script=install.sh

So whats happening here. There are four main things going on. After we set those variables we’re working with gsutil part of the gcloud tools you installed previously. This first section is uploading your jar to google storage so our VM can access it. The first line gsutil mb gs://${BUCKET_NAME} simply tries to make a bucket. After the first run this will error out but the script will continue, thats fine.

The second to last command creates a custom firewall rule for this app to ensure we can access our app.

The last command is creating our instance and on the last line you can see where it passes in our install.sh script for the vm to use

That should be it lets deploy!

  $ chmod 755 start.sh
  $ ./start.sh

Wait a bit for everything to setup. You’ll see the external IP listed in the command completion

After this command comes back the server is still running that script we sent so give it time to load, that java install can take a minute or two. When its done you should see it at `

http://<vm ip address>

Cleanup scripts

Ok now lets not forget to cleanup after ourselves go ahead and create a stop.sh script and copy in the following contents

#! /bin/bash
VM_NAME=gcedeploy

gcloud compute firewall-rules delete --quiet ${VM_NAME}-www
gcloud compute instances delete --quiet --zone=us-central1-a ${VM_NAME}

Update the permissions and tear it down

  $ chmod 755 stop.sh
  $ ./stop.sh
#java, #google, #gcp, #compute engine, #spring, #maven, #gcloud, #gsutil,