Deploy a RESTful Go API with Gin on Koyeb
Tags: webdev, tutorial, go, docker
Published: 2021-08-24 16:09:12

In this guide, we will explain how to build and deploy a Go API using the Gin framework on the Koyeb serverless platform.

[Gin](https://github.com/gin-gonic/gin) is a web framework written in Go focusing on performance. It provides an elegant way to write web applications and microservices and comes with a set of commonly used primitives like routing, middleware, rendering, and more.

By deploying your application on Koyeb, you benefit from powerful primitives including native autoscaling, automatic HTTPS (SSL), auto-healing, and global load-balancing across our edge network with zero configuration.

## Requirements

To successfully follow and complete this guide, you need:
- The Go programming language installed
- [Docker](https://docs.docker.com/get-docker/) installed on your machine
- A [Koyeb account](https://app.koyeb.com) to deploy and run the Go web API
- The [Koyeb CLI](https://www.koyeb.com/docs/cli/installation) installed to interact with Koyeb from the command line
- Have a registry that we will use to store our Go web app Docker image and deploy it on Koyeb

## Steps

To successfully complete this guide and deploy the Go API on Koyeb, you need to follow these steps:

1. [**Building the Go API using Gin**](#building-the-go-api-using-gin)
2. [**Dockerize the Go application**](#dockerize-the-go-application)
4. [**Deploy the Dockerized Go API on Koyeb**](#deploy-the-dockerized-go-api-on-koyeb)

## Building the Go API using Gin

First, let's get started by creating a new directory in your [GOPATH](https://golang.org/doc/gopath_code#GOPATH) to build our sample application:

```bash
mkdir $GOPATH/src/go-demo
cd $GOPATH/src/go-demo
```

In this guide, we name the directory `go-demo`. You can name the folder whatever you like.

Next, run `go mod init` to create a `go.mod` file and track your code's dependencies. As you add dependencies, the `go.mod` file will list the versions your code depends on allowing you to keep your builds reproducible and gives you direct control over which module versions to use.

In your project folder, create a new file named `server.go` with the following content inside:

```go
package main

import (
	"fmt"
	"os"

	"github.com/gin-gonic/gin"
)

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		port = "8000"
	}

	r := gin.Default()

	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "Hello, world!",
		})
	})

	r.GET("/:name", func(c *gin.Context) {
		name := c.Param("name")

		c.JSON(200, gin.H{
			"message": fmt.Sprintf("Hello, %s!", name),
		})
	})

	r.Run(fmt.Sprintf(":%s", port))
}
```

The code above launch a Gin server listening on port 8000 by default with two API routes configured:

- `/` returning "Hello, world!"
- `/:name` returning "Hello, :name!" where :name is the string passed in parameter, i.e /john will return "Hello, john!".

Then, in your terminal execute `go mod tidy` to add missing modules required by our project and add `github.com/gin-gonic/gin` as a project dependency.

You can now run the application locally running `go run server.go` and navigate in your browser at `http://localhost:8000`.

## Dockerize the Go application

To Dockerize our Go application, create a `Dockerfile` in your project directory.
In this guide, we use [Docker multi-stage build](https://docs.docker.com/develop/develop-images/multistage-build/) to keep the image layers size as small as possible and to ensure our image contains only what is needed to run.

In your Dockerfile, copy the content below:


```dockerfile
FROM golang:1.16-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod download
RUN go build -o ./go-demo ./server.go


FROM alpine:latest AS runner
WORKDIR /app
COPY --from=builder /app/go-demo .
EXPOSE 8000
ENTRYPOINT ["./go-demo"]
```

The first stage is used to install dependencies and build our application, in the second one we copy the application binary from stage one and use it to run the application.

To build the Docker image execute the following command in your terminal:

```bash
docker build . -t <DOCKER_HUB_USERNAME>/go-demo
```

*In this guide we will push the Docker image to the Docker Hub. You are free to use another different registry as Koyeb allows you to deploy from any container registry.*

Once the build is completed, you can run a container using the image locally to validate everything is working as expected running:

```bash
docker run -p 8000:8000 <DOCKER_HUB_USERNAME>/go-demo
```

If everything goes well, your container starts properly, you can test the routes using curl:

```bash
$curl localhost:8000/
Hello, world!
```

Next, we can push the Docker image to a container registry, in this guide, the Docker Hub using the following command:

```bash
docker push <DOCKER_HUB_USERNAME>/go-demo
```

On the push command is completed, the Docker image is stored on the container registry and we can deploy it on Koyeb.

## Deploy the Dockerized Go API on Koyeb

We are now ready to deploy our Go web application on Koyeb. First, create a Koyeb Secret to store your container registry configuration.
In this guide, we will deploy our app from the Docker Hub. For other container registries example, check out the related [documentation](/docs/apps/private-container-registry-secrets).

*Note: if your Docker image is public, there is no need to create a secret containing your container registry configuration.*

```bash
echo \
'{
  "auths": {
    "index.docker.io/v1/": {
      "username": "<REPLACE_ME_WITH_DOCKER_HUB_USERNAME>",
      "password": "<REPLACE_ME_WITH_DOCKER_HUB_TOKEN>"
    }
  }
}' | koyeb secrets create docker-hub-credentials --value-from-stdin
```

We can now deploy the Go web application on Koyeb Serverless Platform running:

```bash
koyeb app init go-demo --docker "<REPLACE_ME_WITH_DOCKER_HUB_USERNAME>/go-demo" --ports 8000:http --routes /:8000 --docker-private-registry-secret docker-hub-credentials
```

This command creates a new Koyeb App and deploys our Go application exposing port 8000 and making it publicly accessible on the `/` route of your Koyeb App URL.

To retrieve your Koyeb App URL and access your application, run:

```bash
$koyeb app get go-demo
ID                                  	NAME           	DOMAINS                             	UPDATED AT
d58ebed1-48c0-46b7-a2f1-91f3ffdbccf2	go-demo        	go-demo-<YOUR_ORG>.koyeb.app	2021-06-23 09:46:55.411403 +0000 UTC
```

Open the URL in your browser to access your application running on Koyeb and natively offering autoscaling, automatic HTTPS (SSL), auto-healing, and global load-balancing across our edge network.