AI Code Review for Dockerfiles and Container Images: The Checklist Before an Image Ships
The one-line version bump nobody reviews ships to every environment at once. The seven questions a reviewer must ask about a Dockerfile, why a diff-only reviewer cannot answer them, and how to make them run on every image PR.

A Dockerfile change is the pull request that gets the least review per line of consequence. It is short, it is boring, the diff is usually a version bump or a new RUN line, and the person approving it is rarely the person who will be paged when the image is 2 GB larger, runs as root, or quietly stopped getting security patches because a tag was pinned to a digest nobody refreshes. The build passes, the container starts, and the bug ships inside every environment at once.
This post is a checklist of what an AI code reviewer should verify on a Dockerfile or container-image PR, written so you can turn it into review instructions for whichever tool you run. It is the container-image companion to our checklists for infrastructure-as-code and dependency updates, and it follows the same rule: most of it applies to any reviewer, and where PURA does something specific we say so.
Why Dockerfiles defeat the default review
A Dockerfile is a program whose output is a filesystem, and the diff shows you the program, not the output. Whether FROM node:24 is safe depends on which variant that tag resolves to this week and what is inside it. Whether a new COPY . . is safe depends on the .dockerignore file, which is not in the diff. Whether a RUN apt-get install line is reproducible depends on a cache-busting idiom three lines above it. And whether the image will run at all in production depends on the platform, the user, and the entrypoint that the orchestrator expects, none of which the diff mentions.
A reviewer that reads only the changed lines therefore produces the familiar failure: a confident approval of a change whose risk lives in another file or on a registry. We covered that failure mode in general in why diff-only reviewers miss real bugs. For images it has an extra twist, because the thing being reviewed is cached, layered and rebuilt by machines, so a mistake tends to be invisible until a cache miss.
The checklist
1. Is the base image pinned, and pinned the right way?
FROM python:3 is a moving target; FROM python:3.13-slim is better; FROM python:3.13-slim@sha256:... is reproducible. The reviewer should flag an unpinned or floating tag, and should flag the opposite problem too: a digest pin with no mechanism to refresh it, which freezes the image on whatever CVEs it had the day someone copied the hash. The useful review comment names both halves: pin to a digest, and point at the automation (a dependency bot or a scheduled rebuild) that will bump it. If the repository has neither, that is a finding about the repository, not the PR, and the reviewer should say so once rather than on every Dockerfile.
2. Does the image still run as root?
A Dockerfile with no USER instruction runs as root, and most of them do. The reviewer should check whether the final stage sets a non-root user, whether the files that user needs are owned or readable accordingly (a COPY --chown or a chown step), and whether anything in the entrypoint quietly needs root anyway, such as binding port 80 or writing to a path only root owns. A PR that adds a USER line without fixing the permissions is the most common way to turn a working image into one that crashes on first write.
3. Where do the secrets go?
Three patterns leak secrets into images and all three look innocent in a diff. A COPY . . with a weak .dockerignore copies .env, .git and the SSH key someone left in the repo. An ARG TOKEN used in a RUN line persists in the layer history even if the file is deleted afterwards. And an ENV set to a credential is visible to anyone who can inspect the image. The reviewer should flag build arguments that look like credentials, recommend BuildKit secret mounts for anything a build step needs, and check the .dockerignore whenever the COPY surface changes. This is one of the checks where repository-wide context matters most, because the ignore file is almost never in the diff.
4. Will the layer cache do what the author thinks?
Order decides both build time and correctness. Copying the whole source tree before installing dependencies invalidates the dependency layer on every commit; copying the lockfile first and installing before the source is the standard fix. In the other direction, apt-get update in its own layer, separated from the install that follows, is a classic cache bug: the update is cached, the package list goes stale, and the install starts failing weeks later on a cache hit. The reviewer should check that update and install share a RUN, that the package cache is cleaned in the same layer, and that the expensive, rarely-changing steps come before the cheap, frequently-changing ones.
5. Is the final image the small one?
Multi-stage builds are the norm for compiled languages and increasingly for everything else, and the mistake is subtle: a COPY --from=build that pulls in the whole build directory, or a final stage that is still the full SDK image because somebody needed one tool from it. The reviewer should ask what the final stage is based on, what is copied into it, and whether development dependencies, compilers, test fixtures and documentation made it across. Image size is not the real cost; attack surface and pull time are, and both scale with what you forgot to leave behind.
6. Does the container start, stop and report health the way the platform expects?
A CMD written in shell form runs under /bin/sh -c, so the process is not PID 1 and never receives the SIGTERM that Kubernetes or Compose sends; the container is killed after the grace period instead of stopping cleanly. The exec form fixes it. The reviewer should also check whether a HEALTHCHECK exists or is expected, whether EXPOSE matches the port the application actually listens on, and whether ENTRYPOINT and CMD compose the way the author assumes. These are the findings that only surface in production, during a rolling deploy, which is the worst time.
7. Is the build reproducible across platforms and builders?
An image built on an Apple Silicon laptop and pushed by hand is a different artifact from one built in CI on amd64, and a PR that assumes one platform can break the other. The reviewer should flag a hard-coded architecture in a download URL, a --platform that disagrees with the deployment target, and any step that reaches out to the network for an unpinned file (curl | sh is the obvious one). If the repository builds multi-platform images, the reviewer should check that every stage can.
Turning the checklist into review rules
Write the policy down, not the checklist. A reviewer told to “check Dockerfiles for best practice” will produce a wall of generic advice. A reviewer told “base images must be pinned to a digest; the final stage must set a non-root user; apt-get update and install must share a layer; no ARG may be used for credentials” produces findings a human can accept or reject in one glance. The mechanics of encoding team policy are in custom rules that actually work.
Give it the files outside the diff. The .dockerignore, the compose file or Helm chart that sets the entrypoint and ports, and the CI workflow that builds and pushes the image are the context that decides whether a Dockerfile change is safe. In PURA the review agent has the whole repository available, so a rule such as “whenever a COPY instruction changes, read .dockerignore and list anything sensitive that would be copied” can actually be executed rather than hoped for.
Decide what blocks. Most image findings should be advisory. A credential passed as a build argument, a COPY that would include a secrets file, and a root-running final stage in a repository whose policy forbids it are reasonable candidates for a blocking finding with a logged override. The trade-offs are the same as everywhere else and are covered in gating vs advisory review.
Keep the scanner. An AI reviewer reads the Dockerfile; an image scanner reads the built image and its CVE list. They answer different questions, and the reviewer is at its best when it can read the scanner's output as context and explain which finding the PR introduced and which were already there. Pointing a reviewer at a Dockerfile is not a reason to turn the scanner off.
What the reviewer still cannot do
It cannot see what a tag resolves to on the registry today, so it cannot tell you whether node:24-slim currently carries a critical CVE; the scanner can. It cannot run the image, so it cannot know that the non-root user it approved lacks write access to a path the application creates at startup; a smoke test can. And it will occasionally be confidently wrong about a platform-specific detail, because base images change what they ship between releases. Treat its review as the person who never forgets to ask the seven questions, not as the person who has run the container.
What it changes is the baseline. Every Dockerfile PR, including the one-line version bump that nobody thought needed a reviewer, gets the same questions asked with the repository open before a human spends attention on it. For a change type whose mistakes ship to every environment in a single push, that is a cheap habit to have.
Frequently asked questions
- Why are Dockerfile changes hard for AI code review?
- Because the diff shows the build program, not its output. Whether a base tag is safe, whether a COPY pulls in a secrets file, or whether a shell-form CMD will ignore SIGTERM depends on the registry, the .dockerignore file and the deployment platform, none of which appear in the changed lines. A reviewer needs repository-wide context and explicit policy to answer those questions.
- What should an AI reviewer check on a Dockerfile PR?
- Whether the base image is pinned and refreshable, whether the final stage runs as a non-root user with the right file ownership, whether any build argument, ENV or COPY leaks a credential, whether the layer order keeps the cache correct and fast, whether the final stage left build tools behind, whether CMD and ENTRYPOINT use the exec form and the ports and health check match the platform, and whether the build is reproducible across architectures.
- What can AI code review not verify about a container image?
- It cannot see what a tag resolves to on the registry today or which CVEs the built image carries; an image scanner does that. It cannot run the container, so it cannot catch a permissions error that only appears at startup. Use the AI review as the reviewer that never forgets the checklist, keep the scanner, and keep a smoke test.
Ready to put your AI review spend on rails?
Install PURA on your GitHub repos and start setting budgets in minutes — not months.
Install PURA for free