By Samkit Jain
Deploying the version one of an app to production for the first time is never a walk in the park. We too faced obstacles when deploying the backend of 91paisa (written in Go) on Amazon Web Services (AWS) Elastic Beanstalk. After multiple trials and support from the AWS Support, we finally deployed the initial version of 91paisa. This article will help you if you too are figuring out how to deploy your Go web app on AWS Elastic Beanstalk.
You can deploy Go web applications on AWS Elastic Beanstalk in a couple of ways:
Uploading the source code
Create a Zip file which contains application.go (entry point of your application) file at the root along with the source code. Also, create three additional files - build.sh, Buildfile and Procfile.
The directory structure will look like:
│ └── db.go
│ └── ...
│ └── api.go
│ └── ...
│ └── index.html
Contents of build.sh
Contents of Contentfile
Contents of Procfile
Now, upload the Zip file to Elastic Beanstalk and wait. If everything works, congratulations! If not, read on.
We followed the same process but the environment health immediately degraded. Digging through the logs we found,
The build command was failing because of project layout
We ran eb ssh to SSH into the instance and could find the files downloaded at /var/app/current/ (GOPATH) meaning that the datastore folder was located at /var/app/current/datastore while the application was looking for it in /var/app/current/src/github.com/91paisa/backend/datastore
The build command was failing because of my project layout. We follow the standard structure (and naming convention) where the source code is located at go/src/github.com/91paisa/backend/ which can be imported by specifying the complete path, i.e. import "github.com/91paisa/backend/datastore". Since beanstalk does not know about the project layout it is not creating one and hence the build was failing.
You can get around this by either (a) using relative paths for your packages in the import statement or (b) dividing the application into packages such that you can install them using go get.
Note: Elastic Beanstalk does not delete the previous files. Example, your source code initially contained just three files — application.go, api.go and cmd.go — you uploaded the Zip and everything works great. Now, you don’t need the cmd.go file and you delete it and re-upload the Zip. On your environment, the cmd.go file will still be present and you’ll have to manually remove it or restart the environment. Whenever the load balancer creates a new instance it contains only the latest files though.
Uploading the binary
Create binary using
GOARCH=amd64 GOOS=linux go build -o bin/application application.go
This will create a bin folder containing the binary. Now, create a Zip file containing the bin folder. You can also add additional files like assets and .ebextensions folder.
The directory structure of the Zip will look like
│ └── application
│ └── index.html
You can also create a shell script to automate the process. A basic shell script that fits my use case:
Don’t forget to chmod +x create_zip.sh. Run it using ./create_zip.
We hope this article helped you in deploying your Go app to AWS Elastic Beanstalk. If you are looking to deploy on EC2 or DigitalOcean, the process becomes much more easier. All you have to do is build the executable binary and run it as a service on the server.
Know a better way to deploy? Please share your knowledge in the comments.
Wanna chat? Drop me a message on on Twitter or connect with me on LinkedIn!