Conectando MySQL na sua aplicação serverless

Recentemente, devido a algumas atividades que andei fazendo no trabalho, escrevi um artigo bem step by step de como configurar um ambiente serverless com Golang localmente. Se você não viu ainda, recomendo muuuito dar uma olhada, pois vamos precisar daquela introdução para seguir com o artigo de hoje.

Meu problema

Pois bem, dessa vez precisei integrar um banco MySQL no projeto, também rodando localmente com Docker, mas infelizmente não achei muita coisa em português. E já que consegui (mesmo na tentativa e erro), resolvi escrever esse outro artigo e espero poder te ajudar.

Requisitos

  • Docker compose

Passo 1: Criar arquivo docker-compose.yaml

Crie um arquivo docker-compose.yaml no seu projeto e cole o código abaixo:

version: '3'

services:
    database:
        container_name: 'mycontainername'
        image: mysql:5.7
        ports:
            - '3306:3306'
        networks:
            - mysql
        environment:
            MYSQL_DATABASE: 'mydatabase'
            MYSQL_ROOT_PASSWORD: 'root'

networks:
	mysql:

Passo 2: Adicionar a network no seu serverless.yaml

No seu serverless.yaml, na parte de customização do plugin serverless-offline, adicione a flag do dockerNetwork:

custom:
    serverless-offline:
        # A network é composta pelo nome do seu projeto e a network que você definiu no docker-compose.yaml
        dockerNetwork: go-serverless_mysql

Passo 3: Fazer o setup do MySQL em go

Crie uma pasta infra e dentro da pasta infra crie um arquivo mysql.go:

package infra

import (
    "fmt"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

var db *gorm.DB

type SqlClient struct {
    Db *gorm.DB
}

// Função para buscar sempre uma única instância da conexão do banco
func GetConn() *gorm.DB {
    if db == nil {
            db, err := gorm.Open(mysql.Open("root:root@tcp(mycontainername:3306)/mydatabase"))
            if err != nil {
                    fmt.Println(err.Error())
                    return nil
            }
            fmt.Println("Connected with the database")
            return db
    }

    return db
}

func NewSqlClient() *SqlClient {
    return &SqlClient{
            Db: GetConn(),
    }
}

// Função para fechar a conexão com o banco
func (s *SqlClient) Close() error {
    db, err := s.Db.DB()
    if err != nil {
            fmt.Println("Error closing database: ", err.Error())
            return err
    }
    err = db.Close()
    if err != nil {
            fmt.Println("Error closing database: ", err.Error())
            return err
    }
    return nil
}

Agora, adicione o setup dentro da sua função Handler no seu main.go:

func Handler(request events.APIGatewayProxyRequest) (Response, error) {
    sqlClient := infra.NewSqlClient()
    defer sqlClient.Close()
    return Response{
            StatusCode: http.StatusOK,
            Body: "{hello: world}",
    }, nil
}

Passo 5: Configurar Docker compose no Makefile

No seu Makefile, adicione um step antes de subir o serverless-offline:

docker-compose:
    docker compose up -d

dev: docker-compose
    sls offline --useDocker start --host 0.0.0.0

Prontinho, agora você pode rodar localmente o banco MySQL e sua aplicação com:

make dev

Se tudo deu certo, assim que você bater na sua rota de hello-world, você terá esse log no seu terminal:

Connected with the database

Fim

É isso, pessoal! Espero de coração ter ajudado alguém com esse passo a passo simples de como conectar o MySQL na sua aplicação serverless. E se você quiser dar uma olhada mais afundo, aqui o repositório com o código que desenvolvi.