Docker e Go: guia completo para conteinerização de aplicações Golang
A conteinerização tornou-se o padrão de facto para implantação de aplicações modernas. A linguagem Go (Golang) é ideal para ambientes conteinerizados: seus arquivos binários compilados não exigem runtime, e a linkedição estática permite criar imagens Docker mínimas. Neste artigo, vamos analisar o processo de conteinerização de aplicações Go, desde a escrita do Dockerfile até a otimização do tamanho da imagem final.
Por que Go e Docker são a combinação perfeita
Go compila em um único arquivo binário estático que não depende de bibliotecas do sistema. Isso significa que, para executar uma aplicação Go em um contêiner, não é necessário instalar Go Runtime, interpretadores ou dependências adicionais. Como resultado, você obtém:
- Tamanho mínimo de imagem — frequentemente menos de 10-15 MB
- Inicialização rápida — milissegundos, não segundos
- Alta segurança — menos componentes = menos vulnerabilidades
- Simplicidade de deploy — um único arquivo binário em vez de múltiplos scripts e bibliotecas
Vamos analisar isso com um exemplo simples de um servidor HTTP em Go.
Passo 1: Criando a aplicação Go
Para começar, vamos escrever uma aplicação web simples que será conteinerizada. Crie o arquivo main.go:
package main
import ( "fmt" "log" "net/http" "os")
func main() { port := os.Getenv("PORT") if port == "" { port = "8080" }
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Olá do contêiner Go! 🐳") })
log.Printf("Servidor iniciado na porta %s", port) log.Fatal(http.ListenAndServe(":"+port, nil))}Este é um servidor HTTP mínimo que escuta na porta definida pela variável de ambiente PORT (padrão 8080).
Passo 2: Multi-stage build
Para criar uma imagem Docker mínima, usamos multi-stage build. O primeiro estágio é a compilação da aplicação, o segundo é a criação da imagem final apenas com o arquivo binário. Crie o Dockerfile:
# Estágio 1: Compilação da aplicaçãoFROM golang:1.22-alpine AS builder
WORKDIR /app
# Copiamos go.mod e go.sum para cachear dependênciasCOPY go.mod go.sum ./RUN go mod download
# Copiamos o código fonteCOPY . .
# Compilamos o arquivo binário estáticoRUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .
# Estágio 2: Imagem final mínimaFROM alpine:3.19
# Adicionamos certificados CA para HTTPSRUN apk --no-cache add ca-certificates
WORKDIR /root/
# Copiamos o binário do primeiro estágioCOPY --from=builder /app/server .
# Abrimos a portaEXPOSE 8080
# Executamos a aplicaçãoCMD ["./server"]Observe os pontos-chave:
golang:1.22-alpine— imagem leve para compilaçãoCGO_ENABLED=0— desabilita CGO para linkedição estáticaalpine:3.19— imagem Linux mínima (~5 MB)ca-certificates— necessários se a aplicação usar HTTPS
Passo 3: Compilação e execução do contêiner
Compile a imagem Docker e execute o contêiner:
# Compilação da imagemdocker build -t go-hello:latest .
# Execução do contêinerdocker run -d -p 8080:8080 --name go-app go-hello:latest
# Verificaçãocurl http://localhost:8080# Saída: Olá do contêiner Go! 🐳Verifique o tamanho da imagem obtida:
docker images go-hello# REPOSITORY TAG IMAGE ID CREATED SIZE# go-hello latest abc123def456 10 seconds ago 14.2 MBApenas 14.2 MB — isso é extremamente pequeno comparado a imagens em Node.js (centenas de MB) ou Python (dezenas de MB).