Heroku is a beautiful service. Although it doesn’t support Kubernetes or give a so bright range of cloud infrastructure options, it still does a great job by hosting small applications (even for free).
But the remote cloud configuration may be painful. It’s easy and nice until something goes wrong. It’s ok to dive into manuals and documentation, spend hours to understand how things work and so on. You are a developer after all.
But sometimes you don’t want to know that. You just want to deploy you fizz-buzz blockchain service and bring it to live. And you may not want to spend time on configurations and troubleshooting, don’t want to set up a ton of build dependencies fitting to a cloud environment. You just want to let some magic happen and get a 200
status code in your service response. So, let me tell about how to do that fast.
Application
It’s not about the application you want to deploy, but for example, let’s say it will be a simple greetings server written in Go (server.go
).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
// setup port
port := os.Getenv("PORT")
if port == "" {
port = "8000"
}
// handle home page requests
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprint(w, "Hi internet rando!")
})
// serve
err := http.ListenAndServe(":"+port, nil)
if err != nil {
fmt.Println(err)
os.Exit(2)
}
}
It just starts to serve simple greeting on the port specified in the $PORT
environment variable or 8000 by default. Note that Heroku will provide you a service port to bind to the $PORT
environment variable.
Note: if you will choose Go, don't forget to initiate a go module with
go mod init <module_name>
, otherwise you will have to set up a build environment forGOPATH
in Docker.
That is, let’s build it.
Container
Containerization is a really nice thing in a nowadays programmer’s world. You don’t want to rely on any infrastructure environment anymore, don’t have to feel pain while trying to run your script on the foreign land. You can set up everything once and deploy anywhere.
Don’t have a proper version of your language on the hosting platform – not a big deal, just take a proper Docker image.
Fear to run deployment in an unknown environment – fear not, just configure everything you need in your container.
Even if you don’t want to have applications in a huge OS wrapper – you can use a multistage build, i.e. build in Debian and run in Alpine, etc.
So, let’s configure the container (Dockerfile
):
FROM golang:1.12-alpine
WORKDIR /opt/code/
ADD ./ /opt/code/
RUN go build -o greetings server.go
ENTRYPOINT ["./greetings"]
It will build the app and run it when you will start the container.
Deployment
To deploy to Heroku you need to configure the deployment (heroku.yml
):
build:
docker:
web: Dockerfile
Assuming you have created a Heroku app already, we will deploy it. The easiest way is to deploy directly using CLI.
Manual deployment
First, install Heroku CLI and login:
heroku login
Then you need to add Heroku remote to your Git repo. If you don’t have a Git repo yet, create it:
git init
And then set up Heroku:
# greetings-server-example is my app name. Please use yours
heroku git:remote -a greetings-server-example
Then commit changes and push them to the Heroku:
git add --all
git commit -m "initial commit"
git push heroku master
Now you will see the deployment log. If it was successful, you can call the service with
heroku open
That will just open your service in the browser. There you will see:
Hi internet rando!
Automated deployment with GitHub
You can go further and automate this process. Let’s say, you’re hosting the code on a GitHub. So, you can connect the Heroku app to your GitHub repo and automatically deploy each time you push something to the master branch.
Open Heroku Dashboard and go to "Deploy". There click to the GitHub under "Deployment method". Go to App connected to GitHub and choose your repo and press "Connect". Then go to "Automatic deploys" and press "Enable Automatic Deploys". By default, you will connect to a master branch, but you can change it.
Now you are done. As a bonus, you can set a checkbox “Wait for CI to pass before deploy” if you’re using some CI on GitHub.
After a push into GitHub master you will see a new deploy on the “environment” tab:
And you can check the deployment log in the “Activity” tab of Heroku dashboard.
Have fun with your fast deploy!
Top comments (2)
One suggested update:
Heroku wasn't able to use my
heroku.yml
until I told it that I was building a container using:heroku stack:set container
I'm just shocked that Heroku's "Config vars" are not available during build and we're expected to commit sensitive variables to the heroku.yml or just not use their container platform.