Dockerfile Linter and Best-Practice Checker
Line-by-line Dockerfile checks, a fixed version as a diff, and a .dockerignore.
Try before you buy.
- Free preview: every count with the first problems of the report (up to 10), and the first lines of the fixed Dockerfile, its diff and the .dockerignore (up to 20).
- Locked until you unlock it: download and copy.
- Unlock: Pro pass, ₹179 for 30 days, a one-time payment that never renews.
Ways to unlock shows how to get the full result.
Printing this result is locked in the free preview.
Checked as you type, in your browser. Ctrl/⌘ + Enter checks now.
Your .dockerignore (optional)
With it, files your COPY lines take but the .dockerignore excludes are found, and the whole-context warning knows what you leave out.
Findings
Fixed Dockerfile
Suggested .dockerignore
Locked in the free preview. Opens the ways to unlock this result.
Locked in the free preview. Batch runs unlock with a pass.
Locked in the free preview. Query results unlock with a pass.
About the Dockerfile Linter and Best-Practice Checker
Paste a Dockerfile and get line-by-line findings, each with the reason and a link to Docker’s documentation:
- Base images without a pinned tag or digest,
:latest, and build arguments inFROMthat are not declared or leave an invalid image name. - Root: a final image with no
USER, orUSER root. - Packages:
apt-get installwithout-y, withoutapt-get updatein the sameRUN, without--no-install-recommendsor without removing/var/lib/apt/lists;apt-get updatealone in its own layer;apk addwithout--no-cache;yumanddnfwithout-yandclean all;pipcaches. - Risky steps:
ADDwhereCOPYis clearer, downloads without--checksum,curl … | sh, pipes withoutpipefail,sudo,chmod 777. - Secrets in
ENVandARG, which stay in the image for anyone who pulls it. - Commands: shell-form
CMDandENTRYPOINT(your program missesSIGTERM), exec forms that are not valid JSON, aCMDthat a shell-formENTRYPOINTignores, repeatedCMDs. - Docker’s build checks: the deprecated
MAINTAINER, legacyENV key valueandLABEL key value, relativeWORKDIR,EXPOSEwith host ports, stage-name casing and duplicates, constant--platformvalues,COPY --fromnames that are a typo of a stage, and files that your.dockerignoreexcludes.
The page also writes a fixed Dockerfile with the safe changes made, shown as a diff, suggests a multi-stage build where build tools end up in the image you ship, and writes a .dockerignore for what you build. The rules are MySmartCoPilot’s own, written from Docker’s documentation. Nothing is uploaded. Without a pass the result is a free preview: every count with the first problems, and the first lines of the fixed Dockerfile, the diff and the .dockerignore. The whole report and every copy and download unlock with a Pro pass.
How to use it
- Paste your Dockerfile, open it, or press Load example. Add your
.dockerignoreif you have one: then files it excludes are found, and the “whole context” warning knows what you exclude. - Read the findings: errors break the build or the image, warnings are risks, notes are advice. Show selects the line; each finding links the Docker page it follows.
- Open Fixed Dockerfile to see the safe changes as a diff — merged
apt-get update,-yand clean-ups,COPYfor local files, exec-formCMD,LABELforMAINTAINER. Changes that need your decision, such as aUSERor a pinned version, stay in the findings. - With a pass, or once the result is unlocked, copy or download the fixed Dockerfile, the suggested
.dockerignoreand the report; the free preview shows their first lines and locks the copies and downloads.
Examples
RUN apt-get update RUN apt-get install python3 make g++
RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ \
&& rm -rf /var/lib/apt/lists/*A cached apt-get update layer makes later installs use old package lists; without -y the build stops at the confirmation question.
CMD npm start
CMD ["npm", "start"]
In shell form npm runs under /bin/sh, which does not pass SIGTERM on, so docker stop has to kill it.
ARG NPM_TOKEN RUN npm ci
Warning (SecretsUsedInArgOrEnv): use a build secret instead: RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN … and docker build --secret id=npm_token,env=NPM_TOKEN.
Where the rules come from
Rules that do the same job as one of Docker’s build checks keep its name — JSONArgsRecommended, SecretsUsedInArgOrEnv, UndefinedArgInFrom, CopyIgnoredFile and the others — so you can match them with the output of docker build --check .. The others follow Docker’s building best practices (apt-get, pipes, ADD or COPY, USER, WORKDIR, pinning base images) and the Dockerfile reference (exec and shell form, HEALTHCHECK, here-documents). Secret names are recognised the way BuildKit recognises them: words such as password, secret, token, key or auth as a whole word of the name (DB_PASSWORD, GITHUB_TOKEN, API_KEY_ID), unless another word of it is public, file or version (PUBLIC_KEY, SECRET_FILE).
Multi-stage builds
When one stage installs compilers or runs npm run build, go build, mvn package or similar, everything it needed stays in the image you deploy. A multi-stage build builds in a first stage and copies only the result into a small runtime image: FROM node:24 AS build … RUN npm run build, then FROM node:24-slim with COPY --from=build /app/dist ./dist. The linter points this out; the restructuring is yours.
Limitations
- The linter reads the Dockerfile only: it does not pull base images, so it cannot see the USER, ENV or HEALTHCHECK a base image sets, nor check that packages and files exist.
- Commands inside RUN are read as text (including here-documents), not run in a shell, so unusual scripts may be read too strictly or not strictly enough.
- The fixed Dockerfile only makes mechanical changes; build it and test it before you replace yours.
Privacy
Everything happens in your browser. What you enter or open here is not uploaded or stored by MySmartCoPilot.
Frequently asked questions
What do I get without a pass?
Without a pass, Dockerfile Linter and Best-Practice Checker shows every count with the first problems of the report (up to 10), and the first lines of the fixed Dockerfile, its diff and the .dockerignore (up to 20). Until you unlock it, the result can’t be downloaded or copied. A Pro, Premium or Ultimate pass, a one-time payment that never renews, unlocks the full result. The pricing page lists the passes and their prices.
Is this like hadolint?
It covers similar ground, and adds Docker’s own build-check names, a fixed Dockerfile with a diff and a .dockerignore. The rules are written from Docker’s documentation; no code from hadolint is used. It runs in your browser.
Why should the image not run as root?
A process that breaks out of the application then has root inside the container, and with a mounted socket or a kernel bug possibly on the host. Create a user (RUN useradd --system --uid 10001 app), give it the files it writes (COPY --chown=app), and switch with USER app before CMD.
Should I pin the base image to a digest?
A tag such as node:24-slim can move to a newer image; a digest (@sha256:…) never changes. Docker’s best practices suggest a digest when builds must be reproducible, with a tool such as Dependabot to update it, and a version tag at the least — never latest.
Is my Dockerfile uploaded?
No. It is read and checked in your browser only.