Pular para o conteúdo principal

victorstein.dev

75/100 Dias de Golang - Docker e Golang

Table of Contents

# Docker e Golang

Neste post, vamos criar uma API simples com Golang usando o framework Gin, e empacotá-la em uma imagem Docker enxuta e pronta para deploy.

package main

import (
	"net/http"

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

func main() {
	r := gin.Default()

	r.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "Olá do servidor Go com Gin em Docker!")
	})

	r.Run(":8080")
}

Uma das grandes vantagens do Golang é que ele compila o código em um único executável estático. Isso permite criar imagens Docker extremamente leves, contendo apenas o binário da aplicação. Para aproveitar ao máximo essa característica, vamos utilizar um multi-stage build no Docker. Começaremos mostrando o segundo estágio, responsável apenas por rodar o executável final.. Veja como ela será simples, vamos usar a imagem alpine, definir um workdir, copiar nosso executável, e executar o arquivo compilado.

FROM alpine:3.21

WORKDIR /app

COPY --from=builder /app/api .

EXPOSE 8080

CMD ["./api"]

A primeira etapa é o estágio builder, responsável por instalar as dependências e compilar o executável.

FROM golang:1.24-alpine AS builder

WORKDIR /app

COPY go.mod go.sum* ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o api

Aqui as etapas inicias copiam os dados do projeto e fazem a instalação das libs com base no go.sum. O que quero focar aqui é no comando CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o api. O CGO é desabilitado, é definido o OS como linux e é usado algumas flags para reduzir o tamanho do binário. Na referência que usei para estudar sobre isso a flag CGO_ENABLED era definida como 0, pesquisando mais sobre isso encontrei que o CGO permite que o código Go interaja com código C/C++. No entanto, isso introduz dependências de bibliotecas C que podem variar entre diferentes sistemas operacionais. Ao desativar o CGO, você garante que o binário Go seja compilado puramente em Go, eliminando essas dependências externas. Isso torna o binário mais portátil e menos propenso a problemas de compatibilidade em diferentes ambientes.

Com o dockerfile definido podemos buildar nossa imagem:

docker build -t api-go-gin:latest . 

Veja o resultado: uma imagem com apenas 16MB!

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
api-go-gin   latest    e85a05ab5e21   26 seconds ago   16MB

E agora para rodar nossa API:

docker run -p 8080:8080 api-go-gin:latest

E agora podemos acessar nossa api na rota: http://localhost:8080/

# Referências: