Language and Framework

Deploy Go based apps

This page takes you through setting up instellar for a Gin / GORM application. You will learn how to configure your application to run on your PaaS

Example Application

We’ve created an example application in case you want to skip straight to the source code.

A note on INSTELLAR_ENDPOINT

The examples in the codebase we referenced the .github/workflows/deployment.yml file will contain a value for INSTELLAR_ENDPOINT this is only necessary in those repositories since they’re deploying to our staging environment. For our customers we recommend omitting this value.

The gin / gorm application is built using the default go build command.

main.go

To enable our application to be able to run in multiple modes we’re simply passing in the command line argument either web or migrate.

You can see in the main function.

func main() {
	mode := os.Args[1]

	switch mode {
	case "web":
		web()
	case "migrate":
		migrate()
	default:
		web()
	}
}

This means when we build our application we can pass the mode we want to use and the application will either start the web application or run migrate.

instellar.yml

This file is used to describe to PAKman how to build your application. The following is taken from a gin / gorm based application. This configuration will change depending on your application’s requirements.

Dependencies

Let’s take a look at our dependencies section. You’ll notice that we’re enabling trace: true in our dependencies. This will enable dependency tracing, which means if we miss some dependency in our runtime section the build tool will trace the dependency and automatically include it in our package. Super awesome!

We’re including go in the build section since we need go to build our application.

dependencies:
  trace: true
  build:
    - go
  runtime:
    - bash
    - curl
    - s6
    - jq
    - ca-certificates
    - gemini-openrc

Choosing a Stack

We’re using alpine as the base iamge for all the containers that run the applications. We recommend using alpine/3.17 for all applications. However please check the alpine packages listing to see compatibility for your language and framework. In this case alpine/3.17 will run go 1.19.8.

You can choose from the following:

  • alpine/edge
  • alpine/3.17
  • alpine/3.16
  • alpine/3.15
stack: alpine/3.17

Build

Go has a very simple but powerful build system. In this example we’re simply running go build with the output option to specify where go should output the built binary.

build:
  destinations: 
    - bin
  command: |
    go build -o bin/gemini

Run

The below section explains how your application is run. In this case we’re defining the commands to be able to run migration for our app. The services section is used to define our web service. The default go build will enable us to simply call the binary and pass the command we specified in main.go.

run: 
  name: gemini
  commands:
    - name: migrate
      binary: gemini
      call: 'migrate'
  services:
    - name: web
      binary: gemini
      start:
        call: 'web'

Hooks

These are the lifecycle of the alpine packages. You can define their behaviour. Generally we don’t expect this to change from app to app. However feel free to adjust as required.

In this case rc-update add gemini will add our gemini app to the default run. This will ensure our app automatically starts when the container is restarted (incase it needs to restart).

The rc-service gemini migrate will run the migration. In this case it will run after the package is installed and after the upgrade.

  • rc-service gemini start will start the application
  • rc-service gemini stop will simply stop the application

Your application will be built into openrc and supervised by the s6 supervisor suite.

hook:
  post-install: |
    rc-update add gemini
    rc-service gemini migrate

  pre-upgrade: |
    rc-service gemini stop

  post-upgrade: |
    rc-service gemini migrate
    rc-service gemini start

  post-deinstall: |
    rc-service gemini stop
    rc-update del gemini

Putting it together

The final file looks like the following:

dependencies:
  trace: true
  build:
    - go
  runtime:
    - bash
    - curl
    - s6
    - jq
    - ca-certificates
    - gemini-openrc

stack: alpine/3.17

build:
  destinations: 
    - bin
  command: |
    go build -o bin/gemini

run: 
  name: gemini
  commands:
    - name: migrate
      binary: gemini
      call: 'migrate'
  services:
    - name: web
      binary: gemini
      start:
        call: 'web'

hook:
  post-install: |
    rc-update add gemini
    rc-service gemini migrate

  pre-upgrade: |
    rc-service gemini stop

  post-upgrade: |
    rc-service gemini migrate
    rc-service gemini start

  post-deinstall: |
    rc-service gemini stop
    rc-update del gemini

If you have further suggestions on how we can make this better please don't hesitate to open an issue. Or reach out to us via one of our support channels. If you need a quick support and would like to chat you can join our slack group.