Dockerfile Security & Best Practices Linter
Audit Dockerfiles for security risks (root execution, unpinned tags, hardcoded secrets) and performance bloat in real-time. 100% client-side privacy, zero server telemetry.
Container Executes as Root User (UID 0)
The final production image does not specify a non-root USER instruction.
RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser
Unknown Instruction 'MAINTAINER'
Unknown Dockerfile instruction 'MAINTAINER'. Verify spelling.
Insecure Remote Script Piped to Shell
Piping curl or wget directly into shell ('curl ... | bash') is unsafe.
# Download script, verify SHA256 checksum, then execute
Using ':latest' Base Image Tag 'node:latest'
Avoid using ':latest' tag for base images in production Dockerfiles.
FROM node:<exact-version>
Multi-Stage Build Opportunity Detected
Build toolchains and compilers detected inside a single-stage Dockerfile.
# Convert to multi-stage: FROM base AS builder ... FROM runtime ... COPY --from=builder
Relative WORKDIR Path 'app'
Use absolute paths for WORKDIR instructions.
WORKDIR /app
Standalone 'apt-get update' Instruction
'apt-get update' should be chained in the same RUN layer with 'apt-get install'.
Apt Package Cache Not Cleaned Up
Delete package lists ('rm -rf /var/lib/apt/lists/*') after apt-get install.
RUN apt-get install -y curl git python3 && rm -rf /var/lib/apt/lists/*
Missing HEALTHCHECK Instruction in Final Stage
No HEALTHCHECK instruction defined for container health monitoring.
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1
Use COPY Instead of ADD for Local Files
Prefer 'COPY' over 'ADD' when copying local files or folders.
COPY . .
Missing '--no-install-recommends' in apt-get
Add '--no-install-recommends' to prevent installing non-essential packages.
RUN apt-get install -y --no-install-recommends -y curl git python3
Multiple Consecutive RUN Instructions
Consolidate consecutive RUN instructions using '&& \' to reduce image layers.
Piped Command Without Shell 'pipefail' Option
Pipes in RUN instructions should enable pipefail.
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
Multiple Consecutive RUN Instructions
Consolidate consecutive RUN instructions using '&& \' to reduce image layers.
Multiple Consecutive RUN Instructions
Consolidate consecutive RUN instructions using '&& \' to reduce image layers.
Privileged Port (< 1024) Exposed
Port '80' is below 1024, requiring root privileges to bind.
Shell Form Used for CMD Instruction
Use JSON exec array format for CMD instead of shell form.
CMD ["npm","start"]
Export Dockerfile & CI/CD Audit Report
Download hardened configurations or copy standard Markdown reports for PR comments and security audits.
Dockerfile Security & Best Practices Guide (FAQ)
Essential container security concepts, Hadolint rules, CIS Docker Benchmarks, and multi-stage build optimizations.
Why is running containers as root (UID 0) hazardous?
By default, Docker containers execute processes under the root user. If an attacker exploits an application vulnerability (e.g. remote code execution or path traversal), they gain root privileges inside the container. Combined with any Linux kernel vulnerability or mounted volumes, this enables complete host system compromise. Always declare an unprivileged USER appuser before your CMD or ENTRYPOINT.
What is a multi-stage build and how does it shrink images?
Multi-stage builds allow you to use multiple FROM instructions in a single Dockerfile. You can compile your application in a heavy builder stage containing Node.js, Go, or Maven toolchains, and then copy only the finalized compiled binaries into an ultra-lean runtime image (such as Alpine or Distroless). This reduces final container sizes from 1GB+ down to under 50MB and eliminates compiler attack surface.
Why must you avoid ':latest' or unpinned base tags?
The :latest tag is a moving target that updates upstream whenever upstream publishers push a new version. Builds performed on different days or by different developers can yield divergent runtime environments, breaking deterministic builds and introducing untested zero-day vulnerabilities silently into your production pipeline. Always pin exact semantic versions or SHA256 digest hashes.
How does ToolsAA protect proprietary Dockerfiles?
In strict accordance with our Privacy First Architecture, ToolsAA computes all Dockerfile AST parsing, Hadolint rule matching, and score evaluations 100% inside your local web browser via modern Web APIs. No code, tokens, or Dockerfiles are ever uploaded or transmitted to any external server or telemetry service.
What is the difference between shell form and exec form?
Writing CMD npm start uses shell form, which executes as /bin/sh -c as PID 1. The shell does not forward POSIX signals like SIGTERM to your node application, causing Docker to wait 10 seconds before forcibly issuing SIGKILL. Using JSON exec form CMD ["npm", "start"] runs the process directly as PID 1 for graceful zero-downtime terminations.
How should credentials and secrets be managed in builds?
Never declare secrets in ENV or ARG instructions. Even if you attempt to delete them in later layers, previous layer history retains the secret unencrypted. Use Docker BuildKit secret mounts (RUN --mount=type=secret,id=mysecret ...) which mount credentials in temporary memory during compilation without persisting them to layer cache.