Dockerfile vs buildpacks: ¿cuál deberías usar para tu app?
En resumen
- Con un Dockerfile escribes tú cada paso de la build; los Cloud Native Buildpacks detectan tu lenguaje y construyen la imagen a partir de tu código fuente sin Dockerfile.
- Los buildpacks encajan con apps estándar en lenguajes compatibles y dejan el mantenimiento de la imagen base al builder; un Dockerfile encaja con paquetes de sistema personalizados, stacks poco habituales y control total sobre la imagen.
- Ambos generan una imagen de contenedor, así que puedes empezar con uno y cambiar más adelante.
- En Nodion eliges Buildpacks o Dockerfile por app: las apps con buildpacks escuchan en el PORT que define Nodion, y las apps con Dockerfile, en el puerto de EXPOSE o de la pestaña Processes.
Tanto un Dockerfile como los buildpacks convierten tu código fuente en una imagen de contenedor. La diferencia está en quién escribe los pasos de la build: con un Dockerfile los escribes tú; con buildpacks, el buildpack los deduce a partir de tu código. Usa buildpacks para una app web estándar en un lenguaje compatible, y un Dockerfile cuando necesites control total sobre la imagen o uses un stack que ningún buildpack detecta.
Qué es un Dockerfile
En palabras de la propia Docker, un Dockerfile es “a text document that contains all the commands a user could call on the command line to assemble an image”, es decir, un documento de texto con todos los comandos que un usuario podría ejecutar en la línea de comandos para montar una imagen. Eliges una imagen base, instalas paquetes del sistema, copias tu código, instalas las dependencias y defines el comando de arranque. Tú escribes cada línea: tienes el control total, pero también asumes todo el mantenimiento.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"] Dos características marcan cómo se escriben los Dockerfiles en la práctica:
- Caché de capas: la imagen se construye por capas, y Docker las guarda en caché. Cuando cambia una capa, también se reconstruyen todas las que vienen después. Por eso el ejemplo copia
package.jsone instala las dependencias antes de copiar el resto del código. - Builds multi-stage: varias instrucciones
FROMen un mismo archivo, y cada una inicia una nueva etapa. Compilas en una etapa y copias solo el resultado a una imagen final pequeña, sin compiladores ni herramientas de build.
Qué son los buildpacks
Un buildpack es una herramienta que analiza tu código fuente y deduce cómo construirlo. Los Cloud Native Buildpacks son el estándar abierto para esto. Una build pasa por fases fijas: detect encuentra los buildpacks que encajan con tu código, build convierte el código fuente en artefactos ejecutables (por ejemplo, instalando un runtime y las dependencias y compilando) y export escribe la imagen OCI final. No necesitas un Dockerfile; archivos opcionales como un Procfile o project.toml pueden configurar la build y los procesos.
Tres propiedades distinguen a los buildpacks:
- Imágenes de build y de runtime separadas: los compiladores y las cabeceras están en la imagen de build, y la app se distribuye en la imagen de runtime, sin ellos.
- Rebase: cuando la imagen de runtime recibe una actualización,
pack rebaseapunta la imagen de la app a la nueva base sin volver a hacer la build de la app. - Reproducibilidad: el lifecycle asigna a las capas una marca de tiempo fija, así que el mismo código fuente, el mismo builder y los mismos buildpacks producen la misma imagen, siempre que los propios buildpacks generen una salida reproducible.
Tienes más contexto en Cloud Native Buildpacks: qué son y cómo funcionan.
Dockerfile vs buildpacks de un vistazo
| Dockerfile | Buildpacks | |
|---|---|---|
| Control | Total: imagen base, paquetes, usuarios, estructura de archivos | Dentro de las opciones del buildpack: versiones fijadas, Procfile, paquetes adicionales |
| Mantenimiento | Tú actualizas la imagen base y cada paso | Quien mantiene el builder actualiza el stack y los buildpacks de cada lenguaje |
| Actualizaciones de seguridad | Nueva build con una imagen base parcheada; tienes que darte cuenta tú | Las actualizaciones del builder llevan imágenes base parcheadas a la siguiente build; una imagen ya existente necesita una nueva build o un rebase explícito |
| Reproducibilidad | Depende de lo estrictamente que fijes las imágenes y los paquetes | Incluida de serie para las mismas entradas, con marcas de tiempo fijas en las capas |
| Velocidad de build | Rápida con una caché de capas bien ordenada; un cambio temprano reconstruye todo lo que viene después | Las capas en caché, como las dependencias, se restauran entre builds |
| Multi-stage | Sí, varias etapas FROM | No hace falta: las herramientas de build se quedan en la imagen de build |
| Stacks poco habituales | Cualquier cosa que puedas instalar en una imagen | Solo lo que detecta el builder |
Cuándo elegir buildpacks
- Tu app está escrita en un lenguaje que el builder admite, como Node.js, Python, Ruby, PHP, Go, Rust, Java, .NET o Elixir, o es un sitio estático.
- No quieres mantener tú las imágenes base ni los paquetes del sistema operativo.
- Tienes muchos servicios y quieres que todos se construyan de la misma forma.
- Tu equipo domina el lenguaje, no Docker.
Cuándo elegir un Dockerfile
- Necesitas una imagen base concreta, más paquetes del sistema de los que instala un buildpack o un usuario personalizado.
- El builder no detecta tu lenguaje o tu framework.
- El proyecto ya incluye un Dockerfile que funciona, como pasa con muchas apps open source.
- Quieres una imagen mínima con una build multi-stage, o exactamente la misma imagen en local, en CI y en producción.
Cómo admite Nodion las dos opciones
En Applications → New conectas un repositorio Git y eliges Buildpacks o Dockerfile. El análisis da preferencia al Dockerfile cuando encuentra uno. Puedes cambiar la estrategia más adelante en Settings; el cambio se aplica en el siguiente despliegue. Si haces la build en otro sitio, despliega una imagen ya construida.
Buildpacks en Nodion
- Los propios Cloud Native Buildpacks de Nodion sobre el stack
nodion-26(Ubuntu 26.04 LTS). Detectan Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET y sitios estáticos. - El proceso se ejecuta con un usuario sin privilegios de root. Los paquetes Debian adicionales van en
project.tomlo en unAptfile; sus scripts del mantenedor no se ejecutan. - Un
Procfiledefine los tipos de proceso; si no lo hay, un valor por defecto del lenguaje define el procesoweb. - Puerto: Nodion define
PORT. Escucha en ese puerto; la mayoría de los comandos por defecto usan 8080 si no está definido.
web: gunicorn myapp.wsgi --bind 0.0.0.0:$PORT
worker: python worker.py Dockerfile en Nodion
- El directorio base es el contexto de build, y se respeta el
.dockerignoreque haya en él. - Los archivos multi-stage funcionan. No hay selector de etapa, así que se ejecuta la última etapa.
- Las variables de entorno marcadas como Build se pasan como build args (
ARG). Los secretos de BuildKit no están disponibles. - Puerto: Nodion no define
PORTen una app con Dockerfile. Haz que la app escuche en el puerto del proceso web. Este se rellena a partir deEXPOSEy puedes cambiarlo en la pestaña Processes. Si la lista de puertos está vacía, Nodion usa elEXPOSEde la imagen y, si tampoco lo hay, 8080. Escucha en todas las interfaces, no solo en localhost. - Health check: la readiness se comprueba con una petición HTTP GET a la ruta de health check definida en Settings (por defecto
/). Una respuesta 2xx o 3xx se considera correcta. UnHEALTHCHECKen la imagen se ignora. - Se respeta el
USERde la imagen.
Tienes todos los detalles en la documentación de buildpacks y en la documentación del Dockerfile. ¿Aún no lo tienes claro? Empieza con buildpacks y añade un Dockerfile cuando necesites algo que no puedan hacer.
Preguntas frecuentes
¿Necesito un Dockerfile para desplegar un contenedor?
No. Los buildpacks construyen una imagen de contenedor directamente a partir de tu código fuente, sin Dockerfile en el repositorio. También puedes desplegar una imagen ya construida desde un registry.
¿Son mejores los buildpacks que un Dockerfile?
Ninguno es mejor en general. Los buildpacks necesitan menos mantenimiento en apps estándar con lenguajes compatibles, mientras que un Dockerfile te da control total sobre la imagen y sirve para cualquier stack.
¿Puedo usar un Dockerfile multi-stage en Nodion?
Sí. Los Dockerfiles multi-stage funcionan. No hay selector de etapa, así que la imagen que se ejecuta es la de la última etapa.
¿En qué puerto debe escuchar mi app?
Con buildpacks, escucha en la variable de entorno PORT que define Nodion. Con un Dockerfile, Nodion no define PORT: escucha en el puerto del proceso web, tomado de EXPOSE o configurado en la pestaña Processes, y hazlo en todas las interfaces.