Go
Kubiy compila y ejecuta aplicaciones Go usando systemd como process manager. El flujo de producción compila un binario estático llamado kubiy-app que systemd ejecuta y reinicia si falla.
Presets disponibles
Binario compilado (exec)
Este es el preset recomendado para producción. Kubiy compila tu aplicación en un binario estático llamado kubiy-app y lo ejecuta directamente.
| Parámetro | Valor |
|---|---|
startMode | exec |
| Target | ./kubiy-app (fijo, no configurable) |
| Build por defecto | go build -o kubiy-app . |
El binario siempre debe llamarse kubiy-app y estar en el directorio raíz del proyecto. Kubiy lo busca en esa ubicación específica para iniciarlo.
Ejemplo de configuración:
Preset: Binario compilado (exec)
go run
Modo de desarrollo. Compila y ejecuta la aplicación on-the-fly con go run. No produce un binario persistente.
| Parámetro | Valor |
|---|---|
startMode | go |
| Target por defecto | main.go |
| Build por defecto | ninguno |
Ejemplo de configuración:
Preset: go run
Target: main.go
:::warning Uso en producción
go run recompila la app en cada inicio, lo que añade latencia al arranque y consume recursos de CPU. Úsalo solo para testing o demos. Para producción, usa siempre el preset de binario compilado.
:::
Puerto
Kubiy inyecta tanto PORT como APP_PORT. Tu app debe leer el puerto desde alguna de estas variables:
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, `{"status":"ok"}`)
})
http.ListenAndServe(":"+port, nil)
}
El puerto por defecto es 8080.
El binario kubiy-app
El nombre kubiy-app es obligatorio. Kubiy siempre busca y ejecuta ./kubiy-app en la raíz del proyecto.
Si usas el build por defecto (go build -o kubiy-app .), el binario se genera correctamente. Si especificas un Build Command personalizado, eres responsable de que el output sea ./kubiy-app.
# Correcto — produce ./kubiy-app
go build -o kubiy-app ./cmd/server
# Incorrecto — no produce ./kubiy-app
go build -o mi-app .
Build Command
Si dejas el campo vacío, Kubiy ejecuta:
go build -o kubiy-app .
Esto compila todos los archivos Go en el paquete principal y produce el binario kubiy-app.
Si tu estructura de proyecto es diferente (por ejemplo, el main está en cmd/server/), especifica el Build Command:
go build -o kubiy-app ./cmd/server
Otros ejemplos comunes:
# Con flags de optimización y version embedding
go build -ldflags="-s -w -X main.version=$(git rev-parse --short HEAD)" -o kubiy-app .
# Compilación con CGO deshabilitado (para mayor portabilidad)
CGO_ENABLED=0 go build -o kubiy-app .
# Con módulos en un subdirectorio
cd cmd/api && go build -o ../../kubiy-app .
Cuando especificas un Build Command, ese comando reemplaza completamente el build por defecto. Debes asegurarte de que el resultado es un binario ejecutable llamado kubiy-app en la raíz del proyecto.
Ver la referencia completa de Build Command.
Casos de uso comunes
API con net/http estándar
package main
import (
"encoding/json"
"log"
"net/http"
"os"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})
mux.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"message": "Hello World"})
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Escuchando en :%s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}
Configuración en Kubiy:
Preset: Binario compilado (exec)
Health: /health
Gin Framework
package main
import (
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
r.Run(":" + port)
}
Proyecto con estructura cmd/
Si tu repositorio tiene esta estructura:
.
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ └── ...
├── go.mod
└── go.sum
Configuración en Kubiy:
Preset: Binario compilado (exec)
Build Command: go build -o kubiy-app ./cmd/server
Monorepo o subdirectorio
Si el proyecto Go está en services/api/:
Subdirectorio: services/api
Preset: Binario compilado (exec)
Kubiy usará services/api/ como raíz para el build y el go build -o kubiy-app . se ejecutará en ese directorio.
Variables de entorno disponibles
| Variable | Descripción |
|---|---|
PORT | Puerto asignado (default 8080) |
APP_PORT | Alias de PORT |
KUBIY_DEPLOY_ID | ID del deploy actual |
KUBIY_APP_ID | ID de la aplicación |
import "os"
port := os.Getenv("PORT")
dbURL := os.Getenv("DATABASE_URL")
apiKey := os.Getenv("API_KEY")
Health Check recomendado
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok"}`))
})
El endpoint debe responder en menos de 1 segundo para que Kubiy lo considere exitoso.
Troubleshooting
"kubiy-app not found" o el deploy falla al iniciar
El binario kubiy-app no se generó en la raíz del proyecto. Causas comunes:
- El
mainno está en la raíz — Si tu estructura tienecmd/server/main.go, usago build -o kubiy-app ./cmd/servercomo Build Command. - Build Command personalizado con nombre de binario incorrecto — Asegúrate de que el flag
-oproducekubiy-app. - Error durante el build — Revisa los logs del deploy para ver el error de compilación.
Error de compilación — dependencia no encontrada
Go modules deben estar correctamente configurados. Asegúrate de que:
go.modexiste en la raíz del proyecto (o en el subdirectorio configurado)go.sumestá actualizado (go mod tidylocalmente)- Los módulos se descargan durante el build (
go builddescarga automáticamente)
La app no responde en el puerto correcto
Verifica que tu app escucha en 0.0.0.0 (no solo en localhost):
// Correcto
http.ListenAndServe(":"+port, nil) // equivale a 0.0.0.0:port
http.ListenAndServe("0.0.0.0:"+port, nil)
// Incorrecto — solo acepta conexiones locales
http.ListenAndServe("127.0.0.1:"+port, nil)
Binario no ejecutable (permisos)
Si usas un Build Command que crea el binario de forma no convencional, asegúrate de que el archivo tenga permisos de ejecución. El go build estándar los asigna automáticamente.
CGO y dependencias nativas
Si tu app usa CGO (por ejemplo, sqlite3 con mattn/go-sqlite3), las dependencias nativas deben estar instaladas en el servidor. Por limitaciones del entorno, se recomienda deshabilitar CGO cuando sea posible:
CGO_ENABLED=0 go build -o kubiy-app .
Si necesitas CGO, contacta a soporte para verificar la disponibilidad de las dependencias nativas en el runtime.