Docker e Go: conteinerização de aplicações em Golang
No desenvolvimento moderno, a conteinerização tornou-se o padrão de facto para implantação e escalabilidade de aplicações. Docker e Go são a combinação ideal para criar microsserviços leves, rápidos e seguros. Go compila para um binário estático, o que o torna especialmente atrativo para conteinerização: a imagem final pode pesar apenas alguns megabytes. Neste artigo, vamos analisar como conteinerizar corretamente aplicações Go, otimizar o Dockerfile e evitar erros típicos.
Por que Docker e Go são a combinação ideal?
Go (Golang) foi criado com foco em arquiteturas modernas de nuvem. Suas principais características são compilação estática, suporte embutido para concorrência e ausência de dependências externas em runtime. Docker, por sua vez, fornece um ambiente isolado para executar aplicações. Juntos, eles permitem criar imagens que:
- Ocupam o mínimo de espaço — a imagem de uma aplicação Go pode ter menos de 10 MB.
- Iniciam rapidamente — o binário estático não requer interpretador ou máquina virtual.
- Escalam facilmente — são ideais para orquestração em Kubernetes.
- São mais seguras — a imagem mínima reduz a superfície de ataque.
Criação de uma aplicação Go simples para conteinerização
Para começar, vamos escrever uma aplicação web simples em Go que iremos conteinerizar. 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, "Hello from Go in Docker! 🐳") })
log.Printf("Server starting on port %s", port) log.Fatal(http.ListenAndServe(":"+port, nil))}Esta aplicação escuta requisições HTTP e retorna uma mensagem de boas-vindas. A porta pode ser definida através da variável de ambiente PORT.
Escrevendo o Dockerfile para a aplicação Go
Agora vamos criar o Dockerfile. Começaremos com uma abordagem básica e depois a otimizaremos.
Dockerfile básico (sem otimização)
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./RUN go mod download
COPY . .RUN go build -o main .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]Este Dockerfile usa multi-stage build — um dos melhores padrões para Go. O primeiro estágio (builder) compila a aplicação, o segundo (imagem final) contém apenas o binário compilado. Esta abordagem evita incluir o compilador e as ferramentas do Go na imagem final.
Dockerfile otimizado (best practices)
Para tornar a imagem ainda menor e mais segura, usamos scratch — uma imagem vazia sem shell e utilitários:
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./RUN go mod download
COPY . .
# Desabilita CGO, ativa otimizaçõesRUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main .
FROM scratch
WORKDIR /root/
COPY --from=builder /app/main .
# Adiciona certificados raiz para HTTPSCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 8080
CMD ["./main"]Otimizações principais:
CGO_ENABLED=0— desabilita CGO, o que reduz o tamanho do binário.-ldflags="-s -w"— remove a tabela de símbolos e informações de depuração.scratch— imagem mínima sem camadas desnecessárias.- Cópia de
ca-certificates.crt— necessária para funcionar com HTTPS.