Go Application deployment on Google App engine flexible environment
Tags: googlecloud, go, devops
Published: 2021-05-26 19:01:55

Google Cloud App Engine is a Platform as a Service product that allows us to deploy apps written in various runtimes, such as:

- Python
- PHP
- Java
- Ruby
- Node
- Go
- Ruby, etc

App Engine provides us with two options: the Standard Environment and the Flexible Environment.


The Standard environment is a cloud-native option because it has a very fast spin-up engine that creates instances for our traffic in milliseconds.

The Flexible environment, on the other hand, is different due to its container-based environment that relies on Compute Engine VMs. This is important for many use cases as we can customize our server as per our usage and requirement. This can be the installation of custom packages like ImageMagick, MuPDF libraries, or SSH into our server or run our own bash script, etc. We can use any type of runtime to run our app, and the important thing is that our app should respond in the default 8080 port unless we make some changes.

Here is a detailed idea of the difference between them. [Here](https://cloud.google.com/appengine/docs/the-appengine-environments)

Here we will be deploying a GO application on Flexible Environment on custom runtime rather than Google App Engine default go runtime as it brings up more concerns, unlike the standard one. We will be adding two files one app.yaml and other Docker file

Lets a take simple GO application that uses GIN web framework to render Hello World to our web browser.

```
package main

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

func main() {
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.String(200, "Hello World")
	})
	r.Run()
}
```

Time to show the world 🤠🤠 . Lets make this say through our App Engine Flexible environment.

**app.yaml**

```
runtime: custom
env: flex
```


This is pretty straightforward, as we are defining our custom image as runtime with a flexible environment. We can add other options for scaling purposes and port settings. Check out here

Now, let create a Docker file that resides into the root directory.

**Docker**

```
# Golang docker image
FROM golang:1.14

# Set necessary environmet variables needed for our image
ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# install build essentials (optional)
RUN apt-get update && \
    apt-get install -y wget build-essential pkg-config --no-install-recommends

# Move to working directory /build
WORKDIR /build

# Copy and download dependency using go mod
COPY go.mod .
COPY go.sum .
RUN go mod download

# Copy the code into the container
COPY . .
COPY . /dist

# Build the application
RUN go build -o main .

# Move to /dist directory as the place for resulting binary folder
WORKDIR /dist

# Copy binary from build to main folder
RUN cp /build/main .

# Export necessary port, default GCP App Engine Port
EXPOSE 8080

# Command to run when starting the container
CMD ["/dist/main"]
```

The docker file will contain all the necessary configuration setup that we need to expose the application over 8080. Here 8080 is our default port for GAE.

Also make sure go.mod and go.sum exists on the root directory so that necessary packages get installed on the deployment system

Now from the gcloud CLI set project on which the application is going to be deployed.

```
 gcloud app deploy
```

After successful deployment, there will be a URL to the application and we have our app successfully deployed on google app engine flexible environment using a custom runtime image.

For more, if we want our application using GORM to connect over Google Cloud SQL, there is some changes to be done.

First, Enable the Cloud SQL Admin API in the project
Under app.yaml, we have to tell our application to allow secure connection or else the application can connect to database, make changes as following

```
runtime: custom
env: flex
beta_settings:
  cloud_sql_instances: $INSTANCE_CONNECTION_NAME$
```

$INSTANCE_CONNECTION_NAME$ is the connection name of our cloud SQL that we can get from its instance detail.

Like before deploy application.

```
gcloud app deploy
```

As the flexible environment, there are many configurations that can be implemented to actually make our system like we want to make and behave as we intend to.