Docker y Go: guía completa para la contenedorización de aplicaciones Golang
La contenedorización se ha convertido en el estándar de facto para el despliegue de aplicaciones modernas. El lenguaje Go (Golang) es ideal para entornos de contenedores: sus archivos binarios compilados no requieren runtime, y el enlace estático permite crear imágenes Docker mínimas. En este artículo analizaremos el proceso de contenedorización de aplicaciones Go, desde la escritura del Dockerfile hasta la optimización del tamaño de la imagen final.
Por qué Go y Docker son la pareja ideal
Go se compila en un único archivo binario estático que no depende de bibliotecas del sistema. Esto significa que para ejecutar una aplicación Go en un contenedor no es necesario instalar Go Runtime, intérpretes ni dependencias adicionales. Como resultado, obtienes:
- Tamaño de imagen mínimo — a menudo menos de 10-15 MB
- Inicio rápido — milisegundos, no segundos
- Alta seguridad — menos componentes = menos vulnerabilidades
- Simplicidad en el despliegue — un solo archivo binario en lugar de múltiples scripts y bibliotecas
Veamos esto con el ejemplo de un servidor HTTP simple en Go.
Paso 1: Crear la aplicación Go
Para empezar, escribamos una aplicación web simple que contenedorizaremos. Crea el archivo 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, "¡Hola desde el contenedor Go! 🐳") })
log.Printf("Servidor iniciado en el puerto %s", port) log.Fatal(http.ListenAndServe(":"+port, nil))}Este es un servidor HTTP mínimo que escucha en el puerto definido por la variable de entorno PORT (por defecto 8080).
Paso 2: Compilación multi-etapa (Multi-stage build)
Para crear una imagen Docker mínima se utiliza la compilación multi-etapa. La primera etapa es la compilación de la aplicación, la segunda es la creación de la imagen final solo con el archivo binario. Crea el Dockerfile:
# Etapa 1: Compilación de la aplicaciónFROM golang:1.22-alpine AS builder
WORKDIR /app
# Copiamos go.mod y go.sum para cachear dependenciasCOPY go.mod go.sum ./RUN go mod download
# Copiamos el código fuenteCOPY . .
# Compilamos el archivo binario estáticoRUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .
# Etapa 2: Imagen final mínimaFROM alpine:3.19
# Agregamos certificados CA para HTTPSRUN apk --no-cache add ca-certificates
WORKDIR /root/
# Copiamos el binario desde la primera etapaCOPY --from=builder /app/server .
# Abrimos el puertoEXPOSE 8080
# Ejecutamos la aplicaciónCMD ["./server"]Presta atención a los puntos clave:
golang:1.22-alpine— imagen ligera para compilaciónCGO_ENABLED=0— desactivamos CGO para enlace estáticoalpine:3.19— imagen Linux mínima (~5 MB)ca-certificates— necesarios si la aplicación usa HTTPS
Paso 3: Compilación y ejecución del contenedor
Compila la imagen Docker y ejecuta el contenedor:
# Compilación de la imagendocker build -t go-hello:latest .
# Ejecución del contenedordocker run -d -p 8080:8080 --name go-app go-hello:latest
# Verificacióncurl http://localhost:8080# Salida: ¡Hola desde el contenedor Go! 🐳Verifica el tamaño de la imagen obtenida:
docker images go-hello# REPOSITORY TAG IMAGE ID CREATED SIZE# go-hello latest abc123def456 10 seconds ago 14.2 MBSolo 14.2 MB — es increíblemente pequeño comparado con imágenes de Node.js (cientos de MB) o Python (decenas de MB).