Ir al contenido

Buscar en la documentación

Busca en la documentación de Skiffly

Go

Despliega servicios de Go en Skiffly con Railpack — detección del módulo, la versión de Go, binarios estáticos y CGO, elegir qué `cmd/` compilar, `PORT`, Postgres y Redis, migraciones y health checks.

Qué detecta Railpack#

MiraEfecto
go.mod, go.work o main.go en el directorio raízel servicio es una app de Go
mise.toml/.tool-versions, luego la directiva go de go.mod, luego RAILPACK_GO_VERSIONla versión del toolchain (por defecto 1.23)
paquete main en la raíz, o el primer cmd/* con main.goqué se compila: go build -ldflags="-w -s" -o out
RAILPACK_GO_BIN=apicompila ./cmd/api en lugar del primero que encuentre
RAILPACK_GO_WORKSPACE_MODULE=services/apicon go.work, qué módulo compilar
CGO_ENABLED=1binario dinámico con gcc/libc disponibles en el build y en runtime (lo necesitan mattn/go-sqlite3 y algunas librerías de imágenes); por defecto es un binario estático con CGO_ENABLED=0

La imagen final contiene el binario y poco más; el comando de inicio es el binario compilado. Las dependencias se descargan reutilizando la caché de módulos de Go entre builds. Los pasos de go generate, sqlc generate o templ que deban ejecutarse antes de compilar van en el comando de build (sqlc generate && go build -o out ./cmd/api), que reemplaza por completo el paso de build de Railpack — conserva el -o out para que el comando de inicio siga encontrando el binario, o define tu propio comando de inicio.

Puerto#

port := os.Getenv("PORT")
if port == "" {
    port = "8080"
}
log.Fatal(http.ListenAndServe(":"+port, mux))

":"+port escucha en todas las interfaces; "localhost:"+port no, y el despliegue falla en su health check. Los frameworks (Gin, Echo, Fiber, Chi) reciben la misma cadena de dirección. Skiffly asigna a PORT el puerto del servicio, 8080 cuando no se define — así que un servicio de Go que usa 8080 por defecto no necesita ninguna configuración.

Postgres y Redis#

skiffly deploy --template postgres
skiffly deploy --template redis
skiffly variables set 'DATABASE_URL=${{Postgres.DATABASE_URL}}' 'REDIS_URL=${{Redis.REDIS_URL}}'

pgx (pgxpool.New(ctx, os.Getenv("DATABASE_URL"))), database/sql con lib/pq, GORM y sqlc aceptan la URL. go-redis interpreta REDIS_URL con redis.ParseURL. Ambos hosts están solo en la red privada.

Migraciones#

En Skiffly no hay fase de release. Opciones que funcionan:

  • Al arrancar, en el códigogolang-migrate o goose como librería, ejecutados antes de ListenAndServe (ambos toman un advisory lock para que las réplicas no compitan). El arranque tiene cinco minutos antes de que el health check se rinda.
  • Comando de inicio — instala la CLI en el build y encadena: comando de build go install github.com/pressly/goose/v3/cmd/goose@latest && go build -o out ./cmd/api, comando de inicio sh -c "goose -dir migrations postgres \"$DATABASE_URL\" up && ./out". La imagen necesita sh; la imagen de runtime de Railpack lo incluye.
  • Comando puntualskiffly ssh -- ./out migrate si el binario tiene un subcomando, o ejecuta la herramienta de migraciones desde tu máquina a través de skiffly connect postgres --print.

Health check#

mux.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })

Define /healthz como ruta del health check. Maneja SIGTERM con http.Server.Shutdown para que los rollouts y reinicios terminen las solicitudes en curso (Skiffly espera a que el contenedor salga después de enviar la señal).

Workers y cron#

Un worker es un segundo servicio del mismo repositorio con RAILPACK_GO_BIN=worker (o un comando de build que apunte a ./cmd/worker) y sin dominio. Tareas programadas: un servicio con programación cron cuyo binario se ejecuta una vez y sale.

Módulos privados#

Railpack descarga los módulos sin credenciales. Para módulos en repositorios privados, haz commit de un directorio vendor/ (go mod vendor; el build lo usa automáticamente), o cambia el servicio a un Dockerfile donde puedas montar un token como secreto de BuildKit (RUN --mount=type=secret,id=GITHUB_TOKEN …, consulta Docker).

Problemas comunes#

SíntomaSolución
[railpack] no main package foundmain.go no está en la raíz ni en cmd/*: define RAILPACK_GO_BIN o un comando de build
Despliegue FAILED, el log muestra listening on localhost:8080escucha en : + puerto
go: go.mod requires go >= 1.24Railpack respeta la directiva go; asegúrate de que sea una versión publicada, o fija RAILPACK_GO_VERSION
undefined: sqlite3 / cgo: C compiler not foundCGO_ENABLED=1, o usa un driver en Go puro (modernc.org/sqlite)
x509: certificate signed by unknown authority en runtimela imagen de runtime tiene certificados CA; esto suele indicar un proxy corporativo o una URL HTTP, no un bundle ausente
El binario funciona en local, exec format error en Skifflycompilado de forma cruzada para la arquitectura equivocada; deja que Railpack lo compile (los nodos son linux/amd64)

Ejemplo#

.skiffly/skiffly.ts
import { defineSkiffly, github, postgres, project, service } from "@skiffly/config";
 
export default defineSkiffly(() => {
  const db = postgres("db");
  const api = service("api", {
    source: github("acme/api"),
    healthcheck: "/healthz",
    port: 8080,
    env: { DATABASE_URL: db.env.DATABASE_URL, RAILPACK_GO_BIN: "api" },
    domain: true,
  });
  return project("acme-api", { resources: [db, api] });
});

Landing: /deploy/go