Go is officially supported on ElasticBeanstalk, and there a several ways to deploy an application. This post is covers building and deploying a Go application as a binary.

You may also follow this process for any other language that produces a linux-compatible binary.

Why?

There’s several reasons why you want to consider doing it this way (over the other alternatives):

  1. Deployment and auto scaling is faster. With only a single binary to pull from S3 onto the node it is extremely to bring up/replace nodes. Especially if your application is large or requires lots of dependencies to be downloaded.
  2. You can use your existing build tools. This is especially useful if your share build scripts with your CI. And there is no scripts to create for Beanstalk.
  3. It removes deployment problems such as any dependencies that may change or become unavailable while the application is running in production. An extension of that is you have an absolute snapshot of a version if you deploy the current or existing version to a new stack (for debugging or testing).
  4. You do not need to rely on the Go runtime environment. Most importantly the version, which can take time to rollout in AWS Linux.

Building the Binary

This mostly comes down to your build process. For me I used:

GOOS=linux GOARCH=amd64 go build -o application -ldflags="-s -w"

There are a few tricks here:

  1. GOOS=linux GOARCH=amd64 ensures that the binary produced will be a 64bit linux executable. Super important for mac/windows users.
  2. -o application names the output file. Beanstalk will look for a binary called application or bin/application. So when it's deployed we won't need to rename the executable.
  3. -ldflags="-s -w" creates a smaller binary that strips some debugging symbols and other stuff we won't need.

Deploying

You can now just use the standard eb CLI:

eb deploy

The Gotchas

So far so good... Despite a fair amount of documentation and examples I ran into several issues:

Missing Application Binary

If you are using git, you may (should) be ignoring the application binary. Beanstalk uses the .gitignore file as well so it won't actually include the binary. It will however include everything else (like the source code, etc). All you need to do is create a file called .ebignore (this is used instead of .gitignore if present):

*
!.elasticbeanstalk
!application

This also ensure that only the executable and beanstalk configuration files are included.

504 Bad Gateway

Beanstalk actually deploys the application behind an nginx instance which port forwards 80 -> 5000. Your application must receive connections on port 5000 (if necessary, this can be overridden in the Beanstalk configuration).