Analizador de buenas prácticas Dockerfile con líneas
Este analizador de buenas prácticas para Dockerfile revisa tres problemas habituales antes de que una imagen llegue al sistema de compilación.
Ejecutar — gratis
Detecta la ausencia de WORKDIR, las imágenes base que emplean la etiqueta mutable latest y las instrucciones RUN consecutivas que pueden crear capas innecesarias. Cada hallazgo incluye una línea de origen, un tipo estable y una explicación directa, útil tanto para quien revisa el archivo como para una comprobación automatizada de integración continua.
Obtenga un informe breve y práctico del Dockerfile
Pegue el contenido completo del Dockerfile en el campo de texto y ejecute la comprobación. La respuesta indica si el archivo supera la revisión, cuenta los hallazgos y describe cada problema con un número de línea que comienza en uno, un tipo estable legible por máquinas y un mensaje conciso. El analizador se centra deliberadamente en tres riesgos frecuentes de mantenimiento y no pretende sustituir una suite completa de seguridad para contenedores. Si falta WORKDIR, el aviso se sitúa en la línea 1 porque afecta al archivo entero. Una instrucción FROM se marca en su propia línea cuando la imagen usa latest de forma explícita o no declara ninguna etiqueta y, por tanto, resuelve a latest. Cuando dos RUN son consecutivos, se señala el segundo y se referencia la línea anterior. Los comentarios y las líneas vacías no ocultan esa relación. Un archivo correcto devuelve una lista findings vacía. Las continuaciones con barra inversa forman una sola instrucción lógica y conservan como posición la primera línea física.
Comprenda por qué importan estas tres prácticas
WORKDIR fija de forma explícita el contexto del sistema de archivos para instrucciones posteriores como RUN, COPY, CMD y ENTRYPOINT. Si no aparece, la compilación hereda silenciosamente el directorio elegido por la imagen base, que podría cambiar tras una actualización. Fijar una imagen FROM mediante una etiqueta versionada o un digest inmutable mejora la reproducibilidad. Tanto una referencia sin etiqueta como latest pueden apuntar a contenido distinto aunque el Dockerfile no haya cambiado. Además, cada RUN suele crear una capa del sistema de archivos. Las órdenes consecutivas de instalación, limpieza o configuración suelen pertenecer a una sola operación de shell, de modo que los archivos temporales se eliminen dentro de la misma capa y el historial resulte más claro. El hallazgo se formula como recomendación porque separar RUN puede ser intencionado para conservar límites de caché útiles. La herramienta no reescribe órdenes ni afirma que todas las combinaciones sean seguras. La decisión final corresponde a quien conoce la compilación, su estrategia de caché y el comportamiento de los comandos ante errores.
Ejecute la revisión antes de compilar la imagen
Integre el analizador en el editor, en un flujo previo al commit o al principio de la integración continua, antes de descargar imágenes base y compilar la aplicación. Envíe el texto original, no una representación ya procesada, para conservar las líneas físicas y las continuaciones. El algoritmo es determinista: la misma entrada siempre genera la misma salida y no utiliza red, reloj, valores aleatorios, daemon de Docker ni estado del entorno. Por ello también sirve para Dockerfiles generados. Considere el informe una señal básica de mantenibilidad, no una prueba de seguridad ni de que la imagen pueda compilarse. No ejecuta órdenes de shell, no resuelve variables en nombres de imagen, no inspecciona paquetes, no valida orígenes COPY, no exige un USER sin privilegios y no busca vulnerabilidades. Combine esta revisión rápida con una compilación real, análisis de imágenes, políticas y pruebas del proceso resultante. Si la entrada solo contiene espacios o comentarios, la solicitud falla porque no existen instrucciones que evaluar.
Qué puede hacer con ella
Revise un Dockerfile antes del commit
Detecte referencias mutables y directorios de trabajo ambiguos mientras todavía edita las líneas afectadas.
Controle definiciones de contenedor generadas
Compruebe la salida de plantillas antes de que la canalización invierta tiempo en compilar y publicar una imagen.
Evalúe un repositorio de contenedores
Genere hallazgos coherentes con líneas para priorizar mejoras sencillas en varios servicios.
Preguntas frecuentes
¿Cuánto cuesta una solicitud de análisis?
Cada solicitud API cuesta $0.002. También puede ejecutar la versión del navegador directamente en esta página.
¿Una imagen sin etiqueta cuenta como latest?
Sí. Docker interpreta la ausencia de etiqueta como latest, por lo que se recomienda una versión explícita o un digest.
¿La herramienta combina automáticamente los RUN?
No. Informa de RUN consecutivos, pero no los reescribe porque los límites de caché separados pueden ser intencionados.
¿Por qué un WORKDIR ausente aparece en la línea 1?
La omisión afecta a todo el archivo y no tiene línea propia; por eso se utiliza la línea 1 como ubicación global.
¿Valida la sintaxis o la seguridad del Dockerfile?
No. Aplica tres comprobaciones básicas y debe complementarse con compilación, políticas y análisis de vulnerabilidades.
Para desarrolladores — acceso por API
Todo lo de esta página está disponible por programación. Esta sección es para equipos que quieren integrarlo en sus sistemas; el resto puede usar la herramienta de arriba sin más.
Endpoint de API
¿Prefiere automatizarlo? Un POST autenticado crea la tarea; el resultado llega por webhook o enlace firmado. La misma capacidad también se ejecuta aquí en la web, por email y desde Telegram — y pronto también desde nuestra app.
Llámela desde su stack
curl -X POST https://api.kit.forhosting.com/dev2/dockerfile-lint-basic \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci && npm cache clean --force\nCOPY . .\nCMD [\"node\", \"server.js\"]"}'const res = await fetch("https://api.kit.forhosting.com/dev2/dockerfile-lint-basic", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci && npm cache clean --force\nCOPY . .\nCMD [\"node\", \"server.js\"]"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev2/dockerfile-lint-basic",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci && npm cache clean --force\nCOPY . .\nCMD [\"node\", \"server.js\"]"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev2/dockerfile-lint-basic", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"FROM node:20-alpine\\nWORKDIR /app\\nCOPY package*.json ./\\nRUN npm ci && npm cache clean --force\\nCOPY . .\\nCMD [\\"node\\", \\"server.js\\"]"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci && npm cache clean --force\nCOPY . .\nCMD [\"node\", \"server.js\"]"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev2/dockerfile-lint-basic", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Ejemplo de solicitud
{
"text": "FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci && npm cache clean --force\nCOPY . .\nCMD [\"node\", \"server.js\"]"
}Ejemplo de respuesta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev2.dockerfile_lint_basic",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}La API es asíncrona: la llamada devuelve un task_id al instante y el resultado llega por webhook. El polling está limitado a 1 req/s por tarea.
Precio
Precio publicado — sin tokens ni créditos inventados. Una tarea fallida no se cobra.
Errores
| HTTP | Código | Significado |
|---|---|---|
401 | unauthorized | API key ausente o inválida. |
402 | insufficient_balance | El saldo no cubre el precio de la tarea. |
404 | unknown_type | El tipo de tarea no existe. |
429 | rate_limited | Demasiadas peticiones. Use el webhook en vez de sondear. |