Hora de colocar a mão na massa. Vamos criar uma aplicação Go simples, dockerizar e rodar localmente.
Passo 1: Criar a aplicação Go
Crie uma pasta minha-app/ e dentro dela um arquivo main.go:
go
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
)
type Response struct {
Message string `json:"mensagem"`
Hostname string `json:"hostname"`
Timestamp time.Time `json:"timestamp"`
}
func handler(w http.ResponseWriter, r *http.Request) {
hostname, _ := os.Hostname()
resp := Response{
Message: "Olá do container!",
Hostname: hostname,
Timestamp: time.Now(),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
}
func health(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "OK")
}
func main() {
porta := os.Getenv("PORT")
if porta == "" {
porta = "8080"
}
http.HandleFunc("/", handler)
http.HandleFunc("/health", health)
log.Printf("Servidor escutando na porta %s", porta)
log.Fatal(http.ListenAndServe(":"+porta, nil))
}E o go.mod:
bash
go mod init minha-appPasso 2: Criar o Dockerfile (multi-stage)
Aqui um truque importante: multi-stage build. Compila numa imagem grande e copia só o binário pra uma imagem mínima.
dockerfile
# === Estágio 1: BUILD ===
FROM golang:1.26-alpine AS builder
WORKDIR /build
# Aproveitando cache de dependências
COPY go.mod go.sum* ./
RUN go mod download
# Copia o código e compila
COPY . .
# Build estático (não precisa de libs externas)
RUN CGO_ENABLED=0 GOOS=linux go build -o server .
# === Estágio 2: RUNTIME ===
FROM alpine:3.19
# Adiciona certificados (para HTTPS funcionar)
RUN apk --no-cache add ca-certificates
# Cria usuário não-root (segurança!)
RUN adduser -D -u 1000 appuser
USER appuser
WORKDIR /app
# Copia só o binário do estágio anterior
COPY --from=builder /build/server .
EXPOSE 8080
CMD ["./server"]Por que multi-stage? A imagem final fica com ~15MB ao invés de ~700MB. Menos superfície de ataque, deploy mais rápido, menos uso de disco.
Passo 3: Criar .dockerignore
Para não copiar lixo pra dentro da imagem:
.git
.gitignore
README.md
*.md
.env
.vscode
.idea
node_modules
__pycache__
*.log
Passo 4: Build e run
bash
# Construir a imagem
docker build -t minha-app:v1 .
# Rodar
docker run -d -p 8080:8080 --name minha-app minha-app:v1
# Testar
curl http://localhost:8080
# {"mensagem":"Olá do container!","hostname":"a3b4c5d6","timestamp":"..."}
curl http://localhost:8080/health
# OK
# Ver logs
docker logs minha-app
# Entrar no container
docker exec -it minha-app sh
# Parar e limpar
docker stop minha-app
docker rm minha-appPasso 5: Docker Compose (bônus)
Se sua aplicação tem múltiplos serviços (app + banco + cache), Docker Compose facilita demais.
docker-compose.yml:
yaml
services:
app:
build: .
ports:
- "8080:8080"
environment:
- PORT=8080
- DB_HOST=db
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=minha_app
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
db_data:bash
docker compose up -d # sobe tudo
docker compose logs -f app # acompanha logs do app
docker compose down # derruba tudo