Deploying a Go app to Heroku

Steve Schwedt
Aug 22, 2018 · 4 min read

I recently deployed my first Go app. I found the process much more challenging than in more established frameworks such as Rails and Express. Go still feels like its in the wild west, with no established best practices or norms. Furthermore, things seem to be changing so that some of the best explanations of how to deploy no longer work. Considering that, I wouldn’t be surprised if my method for deploying a Go 1.10.3 app doesn’t work next year, let alone next month.

One of the biggest challenges is package management. Even though a Go app can run locally with no package management, it won’t work on Heroku. One site lists 15 separate package management tools for Go. Of these, 3 are listed on Heroku’s site as being supported. I attempted to use Govendor and Godep with no success. I successfully added them with the go get command(If there are any Go contributors reading this, please make some feedback to the terminal when running go get to indicate that something is happening, and whether it concluded successfully. Ideally this would include ASCII art of dancing gophers). After that when I attempted to use their CLI with govendor init or godep init, nothing happened.

I discovered dep, https://github.com/golang/dep, which seemed to have better docs, more contributors and commits, and more recent activity than the other options I looked at. Heroku does not list dep as being supported officially, but I did stumble upon this site, https://devcenter.heroku.com/articles/go-apps-with-dep#build-configuration, albiet with a caveat:

Your ticket to the VIP room

Before we install dep, lets go over some project setup. Honestly, I can’t guarantee that every step is completely necessary, but this is what worked for me. The app I am deploying is a simple web server using gorilla/mux, with all code currently residing in a file entitled server.go. The entire project, entitled qs_go is in a folder with the same name. In my earlier attempts to deploy, I created a Procfile.txt with the name of what would be my executable file for running a web server:

web: qs_go

I also created a .godir file with what I think is the name of the directory:

qs_go

In my server.go file, I declared my port to reference an environment variable. I wrote this function to get the port from the environment, or if there isn’t one, it can run on port :3000, which is what it does when running locally:

func getPort() string {
  p := os.Getenv("PORT")
  if p != "" {
    return ":" + p
  }
  return ":3000"
}

This requires “os” to be added to the imports, and I also imported log to record an error if the server fails, as well as several other libraries. After setting the variable r, to be my mux router, and establishing a few routes, I called getPort inside the main() function to start the server:

port := getPort()
  log.Fatal(http.ListenAndServe(port, r))

Now its time to install dep. From the command line, I ran:

$ brew install dep
$ brew upgrade dep

This installed dep on my system. Next, from inside my project folder, I ran:

$ dep init

This created a Gopkg.toml file, a Gopkg.lock file and a vendor/ folder inside my project. The vendor folder contained a gitignored github.com folder containing gorilla, which was the only package from outside the standard Go libraries that I was using.

After that, I added Heroku metadata to the Gopkg.toml

[metadata.heroku]
  root-package = "github.com/apoc64/qs_go"
  go-version = "1.10.3"
  install = [ "./..." ]

Don’t forget the third dot. If you do, the error message will be extremely unhelpful. At this point, the file structure should look something like this:

This is absolutely required for deployment to Heroku

Now you’re ready to deploy. You could use heroku create from the command line, but I prefer to create Heroku apps from their website and attach a github repo. First you should probably commit and push your repo.

From my dashboard on the Heroku site which lists all my apps, I press new, and select Create new app. I named the app and created it. Under the settings tab, scroll down to buildpacks. Click add buildpack and search for heroku/go. Then, under the deploy tab, select GitHub under deployment method. From there I searched for my repository and selected qs_go and connected it.

I enabled automatic deploys from the master branch, but for the first one, I did a manual deploy from master.

This shows the logs during the build, which can give more information than the standard logs. If it works, you can then open the app. Hopefully, if all went well, you too will now have a Go app deployed to Heroku. Good Luck.