Volver al blog
Sistemas Corporativos2026-05-04

Microservicios con Go (Golang) y Docker: Estructura para Escalar

Aprende a estructurar microservicios usando Go y contenedorización con Docker para crear sistemas distribuidos robustos y rápidos.

La arquitectura de microservicios se ha convertido en el estándar de la industria para aplicaciones a gran escala, permitiendo que los equipos trabajen de forma independiente y que los componentes individuales escalen según la demanda. El lenguaje Go (Golang), creado por Google, destaca en este escenario debido a su bajo consumo de memoria, concurrencia nativa (goroutines) y velocidad de ejecución cercana a C.

En este artículo, detallaremos cómo organizar y estructurar microservicios en Go utilizando contenedores Docker.

1. Organización del Repositorio (Estructura de Carpetas)

Seguir una estructura limpia y estandarizada es esencial para que el proyecto continúe siendo legible a medida que crece. El patrón recomendado para proyectos Go es el siguiente:

/mi-microservicio
├── cmd/
│   └── app/
│       └── main.go       # Punto de entrada del sistema
├── internal/
│   ├── handler/          # Controladores HTTP o gRPC
│   ├── model/            # Definición de entidades y reglas de dominio
│   └── repository/       # Comunicación directa con la base de datos
├── pkg/                  # Código compartido (utilidades)
├── Dockerfile            # Configuración del contenedor
└── go.mod                # Gestor de módulos de Go

2. Escribiendo el Dockerfile Optimizado (Multi-stage Build)

Para los microservicios, el tamaño de la imagen Docker afecta directamente al tiempo de despliegue (CI/CD) y al consumo de disco en el clúster. En Go, podemos utilizar el multi-stage build para generar imágenes finales de solo unos pocos megabytes.

Ejemplo de Dockerfile profesional:

# Etapa de Compilación
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o main ./cmd/app

# Etapa Ejecutable Final (Imagen Limpia)
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

Con esta estrategia, eliminamos el compilador de Go y todo el historial del código fuente de la imagen final, dejando solo el binario compilado ejecutándose sobre una base Alpine extremadamente ligera y segura.

3. Levantar y comprobar el binario

El main.go en cmd/app solo tiene que responder en /health para el primer deploy. El resto de la API entra en los paquetes de internal/.

package main

import "net/http"

func main() {
	http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte("ok"))
	})
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

Compose publica el puerto solo en localhost. La imagen final es la del Dockerfile de la sección 2, sin el compilador.

services:
  app:
    build: .
    ports:
      - "127.0.0.1:8080:8080"
docker compose up -d --build
curl -fsS http://127.0.0.1:8080/health
docker image ls

La respuesta ok es el proceso en marcha. docker image ls muestra la imagen final, sin la tag builder. Si el build falla en go.sum, ejecute go mod tidy en la máquina de desarrollo y versione el archivo junto con go.mod.

Conclusión

Combinar el alto rendimiento nativo de Go con el aislamiento de entornos proporcionado por Docker es la base ideal para crear sistemas escalables y listos para ejecutarse en clústeres de Kubernetes. Esta arquitectura garantiza bajos tiempos de respuesta y un uso eficiente de los recursos de CPU y RAM en el servidor.

Ingeniería de software corporativo

Migración y sistemas a medida con la operación en línea durante el cambio.

Hablar con ingeniería