Dockerfile Linter

Check your Dockerfile for best practices, security issues, and common mistakes

Issues will appear here after linting...

What is Dockerfile Linter?

A Dockerfile linter analyzes your Dockerfile for best practices, security vulnerabilities, and common mistakes before you build the image. Issues like running as root, using the :latest tag, not cleaning package manager caches, or embedding secrets in ENV instructions can cause security risks, bloated images, and non-reproducible builds. Catching these problems early saves debugging time and prevents vulnerabilities from reaching production.

How to Use

  1. Paste your Dockerfile content into the editor on the left
  2. Click Lint to run all checks against your Dockerfile
  3. Review errors (must fix), warnings (should fix), and informational notices
  4. Apply the suggested fixes shown below each issue to resolve problems
  5. Re-lint after making changes until only informational notices remain

Why Use This Tool?

Detects :latest tag usage — builds should be pinned to specific versions for reproducibility
Flags missing USER instruction — containers should run as non-root for security
Catches ADD instead of COPY for local files — ADD has unexpected tar extraction and URL fetch behaviors
Warns about missing apt-get clean after package installation — reduces final image size
Identifies potential secrets embedded in ENV variables that should be injected at runtime

Tips & Best Practices

  • Combine RUN apt-get update && apt-get install -y in one line to prevent stale cache issues in Docker layers
  • Use multi-stage builds to keep final images small: build in one stage, copy only the artifacts to a slim runtime stage
  • Pin base image versions with a digest for maximum reproducibility: FROM node:20@sha256:...
  • Order COPY instructions from least-changing to most-changing to maximize layer cache hits
  • Use .dockerignore to prevent accidentally copying secrets or node_modules into the image

Frequently Asked Questions

What is DL3007 and why is :latest bad?

DL3007 is the Hadolint rule for unpinned base image tags. The :latest tag points to a different image every time it is updated upstream. Your Docker build could produce different results on different days — a Monday build might include Node 20.0 and a Tuesday build might include Node 20.1, introducing untested changes. Pin to a specific version (FROM node:20.11.0-slim) for reproducibility.

What is the CIS001 (no USER instruction) risk?

Docker containers run as root by default (UID 0). If an attacker exploits a vulnerability in your application, they gain root-level access inside the container. With container escape vulnerabilities, this can escalate to root on the host machine. Create a non-root user with: RUN useradd -r appuser && USER appuser before your CMD or ENTRYPOINT.

Should I use ADD or COPY for local files?

Always use COPY for local files. ADD has additional behaviors: it auto-extracts tar archives and can fetch files from remote URLs. These magic behaviors make builds harder to reason about and audit. Reserve ADD only for the intentional use case of extracting a local tar archive directly into the image.

When should I NOT use a Dockerfile linter?

A linter cannot catch logical errors in your application code or verify that your container actually works at runtime. It also cannot detect issues that only appear in production environments like network configuration, volume permissions, or resource limits. Always combine linting with integration testing and runtime health checks.

Is my Dockerfile data private when using this tool?

Yes. All linting happens entirely in your browser using client-side JavaScript. Your Dockerfile content is never sent to any server, logged, or stored. The tool works offline once the page has loaded.

What linting rules does this tool check?

The tool checks for: unpinned base image tags (:latest), missing USER instruction (running as root), ADD vs COPY misuse, missing apt-get clean after package installation, potential secrets in ENV variables, RUN commands joined with && for cache efficiency, and missing HEALTHCHECK instruction. These rules are based on the Hadolint and Dockerfile best practices specifications.

Real-world Examples

Fixing a Node.js Dockerfile with multiple issues

A Dockerfile uses :latest, runs as root, and uses ADD instead of COPY. The linter identifies all three issues with specific fixes.

Input
FROM node:latest
ADD . /app
WORKDIR /app
RUN npm install
CMD ["node", "server.js"]
Output
Issues found:
1. [Warning] DL3007: Using :latest tag — pin to a specific version
   Fix: FROM node:20-slim
2. [Error] CIS001: No USER instruction — running as root
   Fix: Add RUN useradd -r appuser && USER appuser
3. [Warning] DL3020: Use COPY instead of ADD for local files
   Fix: Replace ADD with COPY

Optimizing a Python Dockerfile for smaller image size

A Python Dockerfile installs packages without cleaning the cache, resulting in a bloated image. The linter suggests combining and cleaning.

Input
FROM python:3.12
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Output
Issues found:
1. [Warning] Missing USER instruction
2. [Info] Consider using python:3.12-slim for smaller image
3. [Warning] RUN pip install should include --no-cache-dir to reduce image size
   Fix: RUN pip install --no-cache-dir -r requirements.txt

Related Tools