Linter de Dockerfile
Pega un Dockerfile y obtén una revisión instantánea según 38 reglas de buenas prácticas: imágenes base sin fijar o con latest, apt-get update en su propia capa, cachés de paquetes sobrantes, falta de USER sin root, CMD en forma shell, secretos en ENV y más. Cada hallazgo enlaza a su línea y explica por qué importa y cómo corregirlo.
Última actualización:
Reglas (0 activadas)
Desmarca una regla para ignorarla. Tu elección se recuerda en este navegador. También puedes añadir # lint-ignore: DF201 en la línea anterior a una instrucción.
Cómo usar Linter de Dockerfile
- Pega tu Dockerfile en el editor, súbelo o carga uno de los ejemplos.
- Lee la puntuación y el recuento de errores, advertencias y sugerencias; las tarjetas de etapa muestran cuántas capas crea cada etapa.
- Abre cada hallazgo: haz clic en el número de línea para saltar a ella y despliega Por qué importa para ver el razonamiento y un ejemplo corregido.
- Corrige y vuelve a comprobar: el Dockerfile se analiza de nuevo mientras escribes.
- Ajusta las reglas si alguna comprobación no encaja con tu proyecto y luego copia el informe para una revisión de código o un ticket.
Referencia de reglas
Las reglas se agrupan por gravedad. Los errores rompen la compilación o se comportan de forma distinta a lo previsto, las advertencias afectan a la seguridad, el tamaño o la reproducibilidad, y las sugerencias son buenos hábitos.
| Código | Regla | Corrección habitual |
|---|---|---|
| DF101 | FROM debe ser la primera instrucción | Solo ARG puede ir antes de FROM |
| DF102 | Instrucción desconocida | Corrige la errata o restaura la \ que falta en la línea anterior |
| DF103 | JSON no válido en forma exec | CMD ["npm", "start"] con comillas dobles |
| DF104 / DF105 | Nombre de etapa duplicado / COPY --from desconocido | AS nombre único; haz referencia solo a etapas anteriores |
| DF106 | Varios orígenes necesitan un directorio de destino | COPY a.txt b.txt ./ |
| DF107 / DF108 | Puerto EXPOSE no válido / WORKDIR relativo | EXPOSE 8080, WORKDIR /app |
| DF201 / DF202 | Imagen base sin fijar o con :latest | FROM python:3.12-slim |
| DF203 | El contenedor se ejecuta como root | USER app en la etapa final |
| DF204 – DF208 | apt-get: update con install, limpieza de caché, -y, apt frente a apt-get, sin upgrade | apt-get update && apt-get install -y --no-install-recommends … && rm -rf /var/lib/apt/lists/* |
| DF209 / DF210 | Cachés de apk y yum/dnf | apk add --no-cache, dnf clean all |
| DF211 / DF216 | sudo, chmod 777 | Cambios con USER, COPY --chown |
| DF212 / DF313 | ADD para archivos locales, URL sin verificar | COPY; ADD --checksum=sha256:… |
| DF213 | Más de un CMD o ENTRYPOINT | Conserva solo el último |
| DF214 | MAINTAINER está obsoleto | LABEL org.opencontainers.image.authors=… |
| DF215 | Secreto en ENV o ARG | Variables en tiempo de ejecución o RUN --mount=type=secret |
| DF217 | Línea vacía en una continuación | Elimina la línea en blanco |
| DF301 – DF313 | Sugerencias: no-install-recommends, caché de pip, WORKDIR frente a cd, forma exec, RUN combinados, orden de COPY favorable a la caché, pipefail, ENV clave=valor, mayúsculas, HEALTHCHECK, npm ci, número de capas | Consulta la explicación bajo cada hallazgo |
Una estructura de Dockerfile favorable a la caché
Docker vuelve a compilar una capa cuando cambia la instrucción o los archivos que copia, y también todas las capas posteriores. Ordena las instrucciones de la que menos cambia a la que más:
- Imagen base con una etiqueta fijada, y paquetes del sistema instalados y limpiados en un único RUN.
- Solo los manifiestos de dependencias:
package.jsonypackage-lock.json,requirements.txt,go.modygo.sum. - Instalación de dependencias:
npm ci,pip install --no-cache-dir -r requirements.txt,go mod download. - Código fuente:
COPY . ., con un.dockerignoreque excluya.git,node_modulesy los resultados de compilación. - Paso de compilación, idealmente en una etapa separada, y luego copia solo el resultado a una imagen de ejecución pequeña.
- Ajustes de ejecución:
USER,EXPOSE,HEALTHCHECKy unCMDoENTRYPOINTen forma exec.
Con este orden, editar un archivo fuente reutiliza las capas de dependencias en caché y la recompilación tarda segundos en lugar de minutos.
Preguntas frecuentes
¿Qué comprueba un linter de Dockerfile?
Lee cada instrucción y la compara con las prácticas de Dockerfile más recomendadas: imágenes base reproducibles (etiquetas fijadas), capas pequeñas (cachés de paquetes eliminadas en el mismo RUN), seguridad (un usuario sin root, sin secretos en ENV, sin chmod 777), sintaxis correcta (JSON válido en forma exec, instrucciones conocidas, puertos EXPOSE válidos) y eficiencia de la caché de compilación (archivos de dependencias copiados antes que el código fuente).
¿Por qué apt-get update y apt-get install deben ir en el mismo RUN?
Docker guarda en caché cada instrucción RUN como una capa. Si apt-get update tiene su propio RUN, esa capa se reutiliza en compilaciones posteriores incluso después de añadir paquetes a la línea de instalación, así que apt-get trabaja con listas de paquetes antiguas y puede fallar o instalar versiones desactualizadas. Poner ambos en un único RUN, seguido de rm -rf /var/lib/apt/lists/*, actualiza las listas y las elimina en la misma capa.
¿Por qué el linter quiere una instrucción USER?
Salvo que un Dockerfile defina USER, el proceso del contenedor se ejecuta como root. Si la aplicación se ve comprometida, ser root dentro del contenedor facilita escapar al host o manipular los archivos montados. Crea un usuario sin privilegios, instala primero los paquetes y luego cambia con USER en la etapa final.
¿Cuál es la diferencia entre la forma shell y la forma exec?
La forma shell (CMD python app.py) ejecuta el comando a través de /bin/sh -c, así que tu programa es hijo del shell y no recibe SIGTERM cuando el contenedor se detiene; Docker espera 10 segundos y luego lo mata. La forma exec (CMD ["python", "app.py"]) inicia el programa directamente como PID 1, para que pueda cerrarse limpiamente.
¿Cuántas capas son demasiadas?
Docker admite hasta 127 capas en una imagen, pero mucho antes de eso, muchas capas hacen que las descargas sean más lentas y las imágenes más difíciles de inspeccionar. Solo RUN, COPY y ADD añaden capas al sistema de archivos. El linter sugiere combinar instrucciones RUN consecutivas e informa de la etapa final cuando crea más de 15 capas. Las compilaciones multietapa son lo que más ayuda, porque solo la etapa final acaba en la imagen.
¿Es lo mismo que hadolint?
No. Este es un linter independiente que funciona en el navegador, con su propio conjunto de reglas (códigos DF101 a DF313) inspirado en la guía oficial de buenas prácticas de Docker. No ejecuta ShellCheck sobre los comandos RUN. Para pipelines de CI, un linter de línea de comandos es un buen complemento; esta herramienta es práctica para revisiones rápidas y para aprender por qué existe cada regla.
¿Puedo ignorar una regla en una línea?
Sí. Pon un comentario como # lint-ignore: DF201 en la línea justo encima de la instrucción para omitir esa regla allí, o desmarca la regla en la lista de Reglas para desactivarla en todas partes. La lista de reglas se recuerda en tu navegador.
¿Se prueban todas las herramientas de FreeToolCabin para comprobar su calidad y precisión?
Sí. Cada herramienta del sitio pasa pruebas automáticas en navegadores reales para comprobar que el resultado es correcto y que no hay errores. Si encuentras un fallo o tienes una sugerencia, escríbenos a [email protected] y lo revisaremos.