Nixpacks: Build Automatico sin Dockerfile
Nixpacks: Build Automatico sin Dockerfile
Nixpacks es el metodo de build por defecto en Dokploy. Detecta automaticamente el lenguaje, las dependencias y genera una imagen Docker optimizada sin que escribas un solo Dockerfile.
Que es Nixpacks
Nixpacks es un builder open source creado por Railway. Analiza tu repositorio, identifica el lenguaje y framework, y produce una imagen OCI lista para produccion. Internamente usa Nix para resolver dependencias del sistema y genera un Dockerfile multi-stage optimizado.
El flujo es:
- Detect - Analiza archivos clave (
package.json,requirements.txt,go.mod, etc.) - Plan - Decide paquetes del sistema, comandos de install y build
- Build - Genera y ejecuta un Dockerfile multi-stage
Lenguajes soportados
Nixpacks detecta automaticamente estos lenguajes:
| Lenguaje | Archivo de deteccion | Runtime |
|---|---|---|
| Node.js | package.json | Node 20 LTS |
| Python | requirements.txt, pyproject.toml, Pipfile | Python 3.11+ |
| Go | go.mod | Go 1.22+ |
| Rust | Cargo.toml | Rust stable |
| Ruby | Gemfile | Ruby 3.x |
| PHP | composer.json | PHP 8.x |
| Java | pom.xml, build.gradle | JDK 17+ |
| .NET | *.csproj, *.fsproj | .NET 8 |
| Elixir | mix.exs | Elixir 1.16+ |
| Haskell | stack.yaml | GHC 9.x |
| Zig | build.zig | Zig 0.13+ |
| Crystal | shard.yml | Crystal 1.x |
| Dart | pubspec.yaml | Dart 3.x |
| Swift | Package.swift | Swift 5.x |
Deploy de ejemplo: app Python/Flask
Supongamos que tienes una API Flask simple. La estructura del proyecto:
mi-api/
app.py
requirements.txt
El archivo app.py:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/health")
def health():
return jsonify({"status": "ok"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
El archivo requirements.txt:
flask==3.1.0
gunicorn==23.0.0
Pasos en Dokploy
- Ve a Projects y selecciona tu proyecto
- Clic en Create Service > Application
- Asigna un nombre, por ejemplo
mi-api-flask - En la seccion Provider, selecciona tu repositorio de GitHub
- En Build Type, selecciona Nixpacks (es el valor por defecto)
- Clic en Deploy
Dokploy detecta requirements.txt, instala Flask y Gunicorn, y expone la app en el puerto configurado.
Configurar el comando de inicio
Nixpacks intenta adivinar el comando de inicio. Para Flask con Gunicorn, verifica que en la seccion General del servicio el campo Command tenga:
gunicorn app:app --bind 0.0.0.0:$PORT
Si Nixpacks no detecta el comando correcto, configuralo manualmente en el panel.
Como Nixpacks detecta el lenguaje
Nixpacks sigue un orden de prioridad al escanear la raiz del repositorio:
- Busca archivos indicadores (
package.json,go.mod,Cargo.toml, etc.) - Si encuentra multiples, prioriza por especificidad
- Genera un plan de build con las fases: setup, install, build, start
Puedes ver el plan que generaria Nixpacks localmente:
# Instalar Nixpacks
curl -sSL https://nixpacks.com/install.sh | bash
# Ver el plan sin ejecutar el build
nixpacks plan .
# Construir la imagen localmente
nixpacks build . --name mi-app
La salida de nixpacks plan muestra el plan en JSON:
{
"providers": ["python"],
"buildImage": "ghcr.io/railwayapp/nixpacks:latest",
"phases": {
"setup": {
"nixPkgs": ["python311", "gcc"]
},
"install": {
"cmds": ["pip install -r requirements.txt"]
},
"build": {
"cmds": []
}
},
"start": {
"cmd": "python app.py"
}
}
Personalizar el build con nixpacks.toml
Si necesitas ajustar el comportamiento de Nixpacks, crea un archivo nixpacks.toml en la raiz del proyecto:
[phases.setup]
nixPkgs = ["python311", "ffmpeg", "imagemagick"]
[phases.install]
cmds = ["pip install -r requirements.txt"]
[phases.build]
cmds = ["python manage.py collectstatic --noinput"]
[start]
cmd = "gunicorn app:app --bind 0.0.0.0:$PORT --workers 4"
Casos comunes de personalizacion
Agregar paquetes del sistema (por ejemplo, para Pillow o ffmpeg):
[phases.setup]
nixPkgs = ["python311", "zlib", "libjpeg", "ffmpeg"]
Cambiar la version de Node.js:
[phases.setup]
nixPkgs = ["nodejs_22"]
Agregar variables de entorno durante el build:
[variables]
NODE_ENV = "production"
NEXT_TELEMETRY_DISABLED = "1"
Definir multiples fases custom:
[phases.setup]
nixPkgs = ["nodejs_20"]
[phases.install]
cmds = ["npm ci"]
[phases.build]
cmds = ["npm run build"]
[start]
cmd = "npm start"
Configuracion en el panel de Dokploy
Dentro de la configuracion del servicio, la seccion General permite ajustar:
- Build Type: Nixpacks (por defecto)
- Build Path: Directorio raiz del proyecto (util en monorepos, por ejemplo
./apps/api) - Command: Comando de inicio (sobreescribe el que detecta Nixpacks)
En la seccion Environment, puedes agregar variables de entorno que estaran disponibles tanto en build como en runtime.
Cuando usar Nixpacks vs Dockerfile
| Criterio | Nixpacks | Dockerfile |
|---|---|---|
| Velocidad de setup | Rapido, sin configuracion | Requiere escribir y mantener Dockerfile |
| Control sobre la imagen | Limitado a nixpacks.toml | Control total |
| Paquetes del sistema | Se agregan via Nix | Cualquier cosa disponible en apt/apk |
| Multi-stage builds | Automatico | Manual pero flexible |
| Imagen final | Basada en Ubuntu/Nix | Puedes usar alpine, scratch, distroless |
| Reproducibilidad | Alta (Nix es determinista) | Depende de como escribas el Dockerfile |
| Monorepos | Soportado con Build Path | Requiere configurar contexto y paths |
Usa Nixpacks cuando:
- Es un proyecto estandar en un lenguaje soportado
- No necesitas paquetes exoticos del sistema
- Quieres desplegar rapido sin configuracion
- El equipo no tiene experiencia con Docker
Usa Dockerfile cuando:
- Necesitas control total sobre la imagen base
- Tu proyecto tiene dependencias complejas del sistema
- Quieres imagenes minimas (scratch, distroless)
- Tienes un proceso de build no convencional
Debugging de builds con Nixpacks
Si el build falla, revisa los logs en la seccion Deployments del servicio. Los errores comunes:
Dependencia del sistema faltante:
error: Package 'libpq' not found
Solucion: agregar el paquete en nixpacks.toml:
[phases.setup]
nixPkgs = ["python311", "postgresql"]
Version de lenguaje incorrecta:
Si tu proyecto requiere una version especifica, forzala:
[phases.setup]
nixPkgs = ["nodejs_18"]
Puerto incorrecto:
Nixpacks usa la variable $PORT. Asegurate de que tu app la lea:
import os
port = int(os.environ.get("PORT", 5000))
Anterior: Capitulo 5: Primer Deploy | Siguiente: Capitulo 7: Dockerfile y Builds Personalizados