Deploy 7 MB Go VMs effortlessly to AWS

Go is a highly productive language with a broad ecosystem for developing modern applications and microservices. It has the unique advantage of combining a great standard library with garbage collection and fast compilation down to a single native binary.

Today we're going to look at deploying Go applications effortlessly to AWS using Boxfuse.

Go App deployed to AWS using Boxfuse

Boxfuse is based upon 3 core principles:

1. Immutable Infrastructure Creating servers and never modifying them again by treating a server as one immutable unit that is regenerated after every change and promoted unchanged from environment to environment. This eliminates drift and increases reliability by ensuring you run the exact same code in production as the code you tested in test.
2. Minimal Images Analysing your application and generating minimal tailor-made Linux-based images on the fly that are 100x smaller than a typical Linux system and take just seconds to produce.
3. Blue/Green deployments Deploying a new version of an app in parallel to the existing one and only making the switch at the elastic IP or elastic load balancer level once the configured health checks of the new version have passed. Deployments are fully automated and effectively transactional, providing you with zero-downtime updates.

The plan

To see this in action, our plan is to first create a new Go web app which we'll fuse into a minimal Boxfuse image that can be deployed unchanged both on VirtualBox and AWS.

We'll then deploy our image to VirtualBox (great for rapid feedback and quick local tests), push it to the Boxfuse Vault (our secure online repository) and run it on AWS.

And finally we'll update it on AWS with zero-downtime blue/green deployments.

Prerequisites

Before we begin, ensure you have successfully:

  1. created a Boxfuse Account (simply log in with your GitHub account, it's free)
  2. downloaded and installed the latest Boxfuse Client
  3. downloaded and installed the latest version of Go
  4. downloaded and installed the latest version of VirtualBox

Creating the Go application

In this tutorial we are going to create and deploy a simple Go application.

Start by creating a directory for our app:

> mkdir getstarted-go

And navigate to it:

> cd getstarted-go

Now create a file called main.go with the following contents:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love Boxfuse!")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Now let's make sure we are compiling for Linux x64. If you are on Linux already, you can safely skip this step.

Windows users should invoke:

getstarted-go> set GOOS=linux

And Mac OSX users should invoke:

getstarted-go> export GOOS=linux

Now go ahead and compile the app into a single executable:

getstarted-go> go build -ldflags="-s"

Fusing a Boxfuse image and running it locally on VirtualBox

Now it's time to fuse your application into a Boxfuse image and launch an instance of it on VirtualBox:

getstarted-go> boxfuse run -ports.http=8080 -image=getstarted-go:1.0

Creating getstarted-go ...
Mapping getstartedgo-dev-myuser.boxfuse.io to 127.0.0.1 ...
Created App getstarted-go (single-instance / none)
Fusing Image for getstarted-go (ELF64) ...
Image fused in 00:00.517s (7170 K) -> myuser/getstarted-go:1.0
Launching Instance of myuser/getstarted-go:1.0 on VirtualBox ...
Forwarding http port localhost:8080 -> vb-f6dba4e5:8080
Instance launched in 00:03.055s -> vb-f6dba4e5
Waiting for Payload to start on vb-f6dba4e5:8080 (expecting HTTP 200 at / within 300s) ...
Payload started in 00:00.009s -> http://127.0.0.1:8080

In just a few seconds Boxfuse found your application, detected its type, generated an image for it and launched an instance of that image on VirtualBox.

Now open your browser and navigate to this address to see your new application up and running within the VirtualBox VM:

You can also see your newly created image:

getstarted-go> boxfuse ls

Images available locally:
+--------------------------+---------------+-------+---------+--------------+--------+---------------------+
| Image                    |    Payload    | Debug | Runtime |    Ports     |  Size  |    Generated at     |
+--------------------------+---------------+-------+---------+--------------+--------+---------------------+
| myuser/getstarted-go:1.0 | getstarted-go | false | ELF64   | http -> 8080 | 7170 K | 2016-08-08 19:38:56 |
+--------------------------+---------------+-------+---------+--------------+--------+---------------------+
Total: 1

As well as the instance that is running:

getstarted-go> boxfuse ps

Running Instances on VirtualBox in the dev environment :
+-------------+--------------------------+---------------------+-----------------------+---------------------+
|  Instance   |          Image           |        Type         |          URL          |     Launched at     |
+-------------+--------------------------+---------------------+-----------------------+---------------------+
| vb-f6dba4e5 | myuser/getstarted-go:1.0 | 4 CPU / 1024 MB RAM | http://127.0.0.1:8080 | 2016-08-08 19:38:59 |
+-------------+--------------------------+---------------------+-----------------------+---------------------+
Total: 1

Deploying your application to AWS

Now let's deploy the image to AWS. As Boxfuse works with your AWS account, it first needs the necessary permissions to do so. So if you haven't already done it, go to the Boxfuse Console and connect your AWS account now.

Every new Boxfuse account comes with 3 environments: dev, test and prod. dev is your local VirtualBox environment and test and prod are on AWS.

So let's deploy our application to the prod environment on AWS:

getstarted-go> boxfuse run getstarted-go:1.0 -env=prod

Pushing myuser/getstarted-go:1.0 ...
Verifying myuser/getstarted-go:1.0 ...
Waiting for AWS to create an AMI for myuser/getstarted-go:1.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:29.835s in eu-central-1 -> ami-9cf006f3
Creating Elastic IP ...
Mapping getstartedgo-myuser.boxfuse.io to 52.28.244.5 ...
Creating security group boxsg-myuser-prod-getstarted-go-1.0 ...
Launching t2.micro instance of myuser/getstarted-go:1.0 (ami-9cf006f3) in prod (eu-central-1) ...
Instance launched in 00:17.580s -> i-921e9a2f
Creating Cloud Watch Alarm for Instance auto-recovery -> i-921e9a2f-auto-recovery-alarm
Waiting for AWS to boot Instance i-921e9a2f and Payload to start at http://54.93.51.85:8080/ ...
Payload started in 00:28.022s -> http://54.93.51.85:8080/
Remapping Elastic IP 52.28.244.5 to i-921e9a2f ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. myuser/getstarted-go:1.0 is up and running at http://getstartedgo-myuser.boxfuse.io:8080/

Notice that we have now specified an image, as we want to reuse our image unchanged instead fusing a new one.

With that one command Boxfuse has automatically pushed your image to the Boxfuse Vault as well as provisioned, configured and secured all necessary AWS resources. There is no manual work necessary on your behalf.

All you need to do is simply navigate to your new domain to see your Go application in action on AWS:

Bonus: update your application using blue/green deployments

Now let's take things one step further and deploy an update of your application with zero downtime.

Start by modifying main.go with a simple change:

...
fmt.Fprintf(w, "Hi there, I love Boxfuse!")
fmt.Fprintf(w, "Updated by Boxfuse with zero downtime!")
...

Then rebuild the tgz:

getstarted-go> go build -ldflags="-s"

Finally, deploy the new version of your application to AWS:

getstarted-go> boxfuse run -ports.http=8080 -env=prod -image=getstarted-go:2.0

Fusing Image for getstarted-go (ELF64) ...
Image fused in 00:00.541s (7170 K) -> myuser/getstarted-go:2.0
Pushing myuser/getstarted-go:2.0 ...
Verifying myuser/getstarted-go:2.0 ...
Waiting for AWS to create an AMI for myuser/getstarted-go:2.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:14.649s in eu-central-1 -> ami-ba8b7dd5
Creating security group boxsg-myuser-prod-getstarted-go-2.0 ...
Launching t2.micro instance of myuser/getstarted-go:2.0 (ami-ba8b7dd5) in prod (eu-central-1) ...
Instance launched in 00:19.492s -> i-d91f9b64
Creating Cloud Watch Alarm for Instance auto-recovery -> i-d91f9b64-auto-recovery-alarm
Waiting for AWS to boot Instance i-d91f9b64 and Payload to start at http://52.59.244.104:8080/ ...
Payload started in 00:30.181s -> http://52.59.244.104:8080/
Remapping Elastic IP 52.28.244.5 to i-d91f9b64 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Destroying Cloud Watch Alarm i-921e9a2f-auto-recovery-alarm ...
Terminating instance i-921e9a2f ...
Destroying Security Group sg-dbc040b3 (boxsg-myuser-prod-getstarted-go-1.0) ...
Deployment completed successfully. myuser/getstarted-go:2.0 is up and running at http://getstartedgo-myuser.boxfuse.io:8080/

And there it is:

Summary

In this post, we saw how to deploy and update a Go application to AWS using Boxfuse in 3 easy steps.

First we fused our application into a 7 MB Boxfuse image in under 1 second and ran an instance of it on VirtualBox. We then deployed the same image unchanged to AWS. And finally we updated our application on AWS with zero downtime using blue/green deployments.

To do so we used Boxfuse and its 3 core principles: Immutable Infrastructure , Minimal Images and Blue/Green deployments.

Go App deployed to AWS using Boxfuse

And if you are a Revel fan, Boxfuse has you covered with first-class support for running Revel applications!

However this is just the beginning! Boxfuse also supports dead-easy auto-scaling, database auto-provisioning and much more. Not only for Go apps, but also for Node.js and JVM ones.

So if you haven't already, sign up for your Boxfuse account now (simply log in with your GitHub id, it's free) and start deploying your Go applications effortlessly to AWS in minutes.

Join us and stay updated about Boxfuse and Immutable Infrastructure

Interesting posts with low frequency. Unsubscribe at any time.

« Worker Apps
Introducing AWS CloudWatch Logs support with Live Tailing »
Recent posts