Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Idockerfile Processor

Purpose

Lints Dockerfiles with hadolint’s rules, in-process (no hadolint binary). The Rust alternative to the hadolint processor: a port of hadolint 2.15.1’s Dockerfile parser, its # hadolint ignore= pragmas, its .hadolint.yaml configuration and all of its DL rules, so a Dockerfile gets the same findings, with the same messages, codes and severities, and passes or fails the way hadolint would exit.

What is not here is ShellCheck. hadolint runs ShellCheck over every RUN script and reports its SC codes alongside its own; ShellCheck is a separate program with no Rust counterpart, so idockerfile reports DL findings only. A repo that wants the SC findings keeps the hadolint processor.

How It Works

Each Dockerfile is parsed the way hadolint’s parser (language-docker) reads it: instructions and their flags, escaped line breaks, heredocs, the # escape= and # syntax= pragmas, exec-form JSON arrays. RUN scripts are read as hadolint reads them for its rules: which commands run, with which arguments and flags, including commands inside $(...), if, loops and subshells, and whether anything is piped. The 71 DL rules then run over the result, from DL3000 (absolute WORKDIR) through the package-manager rules (apt-get, apk, pip, npm, gem, yum, dnf, zypper, go, yarn) to DL4006 (pipefail). Findings are printed in hadolint’s own format:

Dockerfile:1 DL3006 warning: Always tag the version of an image explicitly
Dockerfile:4 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
Dockerfile:4 DL3015 info: Avoid additional packages by specifying `--no-install-recommends`
Dockerfile:7 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.

A file fails when any finding is at least as severe as the failure threshold (info by default, like hadolint: error and warning and info fail, style does not). A file whose only findings are below the threshold passes, and nothing is printed for it. A Dockerfile hadolint’s parser cannot read fails with the position of the problem.

Configuration

idockerfile reads .hadolint.yaml (or .hadolint.yml) from the project root when one exists, exactly as hadolint run from there would, with the keys hadolint’s checks use: ignored, override (error, warning, info, style lists), trustedRegistries, label-schema, strict-labels, disable-ignore-pragma, failure-threshold, no-fail. config_file names a different file. The TOML fields below add to or override what the file says. Inline pragmas work as in hadolint: # hadolint ignore=DL3008,DL3015 for the next instruction, # hadolint stage ignore=... for the rest of the stage, # hadolint global ignore=... for the file.

[processor.checker.idockerfile]
src_files = ["Dockerfile", "docker/api/Dockerfile"]
ignored = ["DL3059"]
failure_threshold = "warning"

Fidelity

Checked against hadolint 2.15.1 over the fleet’s 154 Dockerfiles, with and without the fleet’s .hadolint.yaml, and over 2000 mutated copies (unpinned installs, missing -y, sudo, cd, pipes, untagged and latest images, bad COPY --from references, duplicate stage names, ONBUILD wrappers, pragmas, heredocs, lower-cased keywords, exec-form commands): the same DL findings, file for file. Two things had to be copied from hadolint rather than reasoned out: its tree walk yields every shell command twice (once for ShellCheck’s redirection wrapper, once for the command), which is what makes DL3059 fire only for single-command RUNs; and a RUN script ShellCheck cannot parse (an unterminated quote, a redirection without a target) contributes no commands at all. One known divergence: hadolint 2.15.1 rejects a heredoc followed directly by the next instruction (a bug in its parser release, fixed upstream since); idockerfile accepts it.

Source Files

  • Input: files named Dockerfile under src_dirs, or the files in src_files
  • Output: none (checker)

The default src_dirs is empty, so a stanza with no src_dirs or src_files checks nothing: name the directories ([""] for the whole project) or files to check.

Configuration

KeyTypeDefaultDescription
config_filestring""A hadolint configuration file (YAML). Empty: .hadolint.yaml or .hadolint.yml in the project root when present
ignoredstring[][]Rule codes to ignore, added to the configuration file’s ignored
trusted_registriesstring[][]Registries FROM images may come from (DL3026); * wildcards allowed
label_schematable{}Labels that must be present, name = type (text, url, semver, hash, rfc3339, spdx, email)
strict_labelsboolfalseForbid labels outside label_schema (DL3050)
disable_ignore_pragmaboolfalseIgnore # hadolint ignore=... pragmas in the files
failure_thresholdstring""Fail only on findings at least this severe: error, warning, info, style, none. Empty: the configuration file’s, else info
src_dirsstring[][]Directories to scan
src_extensionsstring[]["Dockerfile"]File name suffixes to check
dep_inputsstring[][]Extra files whose changes trigger rebuilds
dep_autostring[][".hadolint.yaml", ".hadolint.yml"]Config files that are inputs when they exist

Switching a repo from hadolint: [processor.checker.hadolint] → [processor.checker.idockerfile]; the .hadolint.yaml stays as it is. A repo whose findings include SC codes it wants to keep stays on hadolint.

Batch support

Files are checked individually within a batch, so one bad file fails only its own product.

Clean behavior

This processor is a Checker — rsconstruct clean outputs is a no-op for it (checkers produce no outputs). See Clean behavior and rsconstruct clean.