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/