# tally ## Docs - [AI AutoFix (ACP)](https://tally.wharflab.com/guides/ai-autofix.md): Use ACP-compatible coding agents to fix complex Dockerfile issues that are too risky for deterministic rewrites. - [Auto-fix](https://tally.wharflab.com/guides/auto-fix.md): Apply safe and unsafe auto-fixes to Dockerfiles using tally lint --fix. - [Build invocations](https://tally.wharflab.com/guides/build-invocations.md): Lint Dockerfiles through Docker Buildx Bake and Docker Compose entrypoints. - [CI/CD integration](https://tally.wharflab.com/guides/ci-cd.md): Integrate tally into GitHub Actions, GitLab CI, and pre-commit hooks for automated Dockerfile linting. - [Configuration](https://tally.wharflab.com/guides/configuration.md): Complete reference for tally's config file, environment variables, CLI flags, and inline directives. - [Exit codes](https://tally.wharflab.com/guides/exit-codes.md): Reference for tally's exit codes and how to handle them in scripts and CI pipelines. - [IDE integration](https://tally.wharflab.com/guides/ide-integration.md): Set up real-time Dockerfile linting in VS Code, JetBrains IDEs, and any LSP-compatible editor. - [Installing BuildKit for Windows Containers](https://tally.wharflab.com/guides/installing-buildkit-windows-containers.md): Set up a standalone BuildKit daemon for Windows containers and connect docker buildx with the remote driver. - [Output formats](https://tally.wharflab.com/guides/output-formats.md): Reference for all five tally output formats: text, json, sarif, github-actions, and markdown. - [Installation](https://tally.wharflab.com/installation.md): Install tally via Homebrew, WinGet, npm, pip, RubyGems, Docker, Go, or from source. - [EditorConfig integration](https://tally.wharflab.com/integrations/editorconfig.md): Use EditorConfig settings to keep tally formatting fixes aligned with your repository style. - [Introduction](https://tally.wharflab.com/introduction.md): tally is a BuildKit-native Dockerfile and Containerfile linter and formatter with safe auto-fix, LSP support, and SARIF output. - [Quick start](https://tally.wharflab.com/quickstart.md): Lint your first Dockerfile in under a minute. - [buildkit/ConsistentInstructionCasing](https://tally.wharflab.com/rules/buildkit/ConsistentInstructionCasing.md): Instruction keywords should use consistent casing throughout the Dockerfile. - [buildkit/CopyIgnoredFile](https://tally.wharflab.com/rules/buildkit/CopyIgnoredFile.md): Attempting to Copy file that is excluded by .dockerignore. - [buildkit/DuplicateStageName](https://tally.wharflab.com/rules/buildkit/DuplicateStageName.md): Stage names in a multi-stage build should be unique. - [buildkit/ExposeInvalidFormat](https://tally.wharflab.com/rules/buildkit/ExposeInvalidFormat.md): EXPOSE instruction should not define an IP address or host-port mapping. - [buildkit/ExposeProtoCasing](https://tally.wharflab.com/rules/buildkit/ExposeProtoCasing.md): Protocol names in `EXPOSE` instructions should be lowercase. - [buildkit/FromAsCasing](https://tally.wharflab.com/rules/buildkit/FromAsCasing.md): The `AS` and `FROM` keywords' casing should match. - [buildkit/FromPlatformFlagConstDisallowed](https://tally.wharflab.com/rules/buildkit/FromPlatformFlagConstDisallowed.md): FROM `--platform` flag should not use a constant value. - [buildkit/InvalidBaseImagePlatform](https://tally.wharflab.com/rules/buildkit/InvalidBaseImagePlatform.md): Validates that the platform of an external base image matches the expected target platform. - [buildkit/InvalidDefaultArgInFrom](https://tally.wharflab.com/rules/buildkit/InvalidDefaultArgInFrom.md): Using the global ARGs with default values should produce a valid build. - [buildkit/InvalidDefinitionDescription](https://tally.wharflab.com/rules/buildkit/InvalidDefinitionDescription.md): Comments for build stages or arguments should follow the description format. - [buildkit/JSONArgsRecommended](https://tally.wharflab.com/rules/buildkit/JSONArgsRecommended.md): JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals. - [buildkit/LegacyKeyValueFormat](https://tally.wharflab.com/rules/buildkit/LegacyKeyValueFormat.md): `ENV key=value` should be used instead of the legacy `ENV key value` format. - [buildkit/MaintainerDeprecated](https://tally.wharflab.com/rules/buildkit/MaintainerDeprecated.md): MAINTAINER instruction is deprecated in favor of using label. - [buildkit/MultipleInstructionsDisallowed](https://tally.wharflab.com/rules/buildkit/MultipleInstructionsDisallowed.md): Multiple CMD instructions should not be used in the same stage because only the last one will be used. - [buildkit/NoEmptyContinuation](https://tally.wharflab.com/rules/buildkit/NoEmptyContinuation.md): Empty continuation lines are deprecated and will cause errors in future Dockerfile syntax versions. - [buildkit/RedundantTargetPlatform](https://tally.wharflab.com/rules/buildkit/RedundantTargetPlatform.md): Setting platform to predefined `$TARGETPLATFORM` in FROM is redundant as this is the default behavior. - [buildkit/ReservedStageName](https://tally.wharflab.com/rules/buildkit/ReservedStageName.md): `scratch` is reserved and should not be used as a stage name. - [buildkit/SecretsUsedInArgOrEnv](https://tally.wharflab.com/rules/buildkit/SecretsUsedInArgOrEnv.md): Potentially sensitive data should not be used in the ARG or ENV commands. - [buildkit/StageNameCasing](https://tally.wharflab.com/rules/buildkit/StageNameCasing.md): Stage names in multi-stage builds should be lowercase. - [buildkit/UndefinedArgInFrom](https://tally.wharflab.com/rules/buildkit/UndefinedArgInFrom.md): FROM argument is not declared. - [buildkit/UndefinedVar](https://tally.wharflab.com/rules/buildkit/UndefinedVar.md): Usage of undefined variable. - [buildkit/WorkdirRelativePath](https://tally.wharflab.com/rules/buildkit/WorkdirRelativePath.md): Relative workdir can have unexpected results if the base image changes. - [BuildKit rules](https://tally.wharflab.com/rules/buildkit/overview.md): tally supports all 22 BuildKit checks, including reimplementations of build-time checks as pure static analysis. - [hadolint/DL3000](https://tally.wharflab.com/rules/hadolint/DL3000.md): Use absolute WORKDIR. - [hadolint/DL3001](https://tally.wharflab.com/rules/hadolint/DL3001.md): Command does not make sense in a container. - [hadolint/DL3002](https://tally.wharflab.com/rules/hadolint/DL3002.md): Last user should not be root. - [hadolint/DL3003](https://tally.wharflab.com/rules/hadolint/DL3003.md): Use WORKDIR to switch to a directory. - [hadolint/DL3004](https://tally.wharflab.com/rules/hadolint/DL3004.md): Do not use sudo. - [hadolint/DL3006](https://tally.wharflab.com/rules/hadolint/DL3006.md): Always tag the version of an image explicitly. - [hadolint/DL3007](https://tally.wharflab.com/rules/hadolint/DL3007.md): Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag. - [hadolint/DL3010](https://tally.wharflab.com/rules/hadolint/DL3010.md): Use ADD for extracting archives into an image. - [hadolint/DL3011](https://tally.wharflab.com/rules/hadolint/DL3011.md): Valid UNIX ports range from 0 to 65535. - [hadolint/DL3012](https://tally.wharflab.com/rules/hadolint/DL3012.md): Provide an exact tag for multiple `HEALTHCHECK` instructions. - [hadolint/DL3014](https://tally.wharflab.com/rules/hadolint/DL3014.md): Use the `-y` switch. - [hadolint/DL3020](https://tally.wharflab.com/rules/hadolint/DL3020.md): Use `COPY` instead of `ADD` for files and folders. - [hadolint/DL3021](https://tally.wharflab.com/rules/hadolint/DL3021.md): `COPY` with more than 2 arguments requires the last argument to end with `/`. - [hadolint/DL3022](https://tally.wharflab.com/rules/hadolint/DL3022.md): `COPY --from` should reference a previously defined `FROM` alias. - [hadolint/DL3023](https://tally.wharflab.com/rules/hadolint/DL3023.md): `COPY --from` cannot reference its own `FROM` alias. - [hadolint/DL3024](https://tally.wharflab.com/rules/hadolint/DL3024.md): Duplicate stage names are not allowed. - [hadolint/DL3025](https://tally.wharflab.com/rules/hadolint/DL3025.md): Use arguments JSON notation for CMD and ENTRYPOINT arguments. - [hadolint/DL3026](https://tally.wharflab.com/rules/hadolint/DL3026.md): Use only an allowed registry in the `FROM` image. - [hadolint/DL3027](https://tally.wharflab.com/rules/hadolint/DL3027.md): Do not use `apt` as it is meant to be an end-user tool, use `apt-get` or `apt-cache` instead. - [hadolint/DL3029](https://tally.wharflab.com/rules/hadolint/DL3029.md): Do not use --platform flag with constant value in FROM. - [hadolint/DL3030](https://tally.wharflab.com/rules/hadolint/DL3030.md): Use the `-y` switch to avoid manual input: `yum install -y `. - [hadolint/DL3034](https://tally.wharflab.com/rules/hadolint/DL3034.md): Non-interactive switch missing from `zypper` command: `zypper install -y`. - [hadolint/DL3038](https://tally.wharflab.com/rules/hadolint/DL3038.md): Use the `-y` switch to avoid manual input: `dnf install -y `. - [hadolint/DL3043](https://tally.wharflab.com/rules/hadolint/DL3043.md): `ONBUILD`, `FROM` or `MAINTAINER` triggered from within `ONBUILD` instruction. - [hadolint/DL3044](https://tally.wharflab.com/rules/hadolint/DL3044.md): Do not refer to an undefined variable. - [hadolint/DL3045](https://tally.wharflab.com/rules/hadolint/DL3045.md): `COPY` to a relative destination without `WORKDIR` set. - [hadolint/DL3046](https://tally.wharflab.com/rules/hadolint/DL3046.md): `useradd` without flag `-l` and high UID will result in excessively large image. - [hadolint/DL3047](https://tally.wharflab.com/rules/hadolint/DL3047.md): Use `wget --progress` to avoid excessively bloated build logs. - [hadolint/DL3057](https://tally.wharflab.com/rules/hadolint/DL3057.md): `HEALTHCHECK` instruction missing. - [hadolint/DL3059](https://tally.wharflab.com/rules/hadolint/DL3059.md): Multiple consecutive `RUN` instructions. - [hadolint/DL3061](https://tally.wharflab.com/rules/hadolint/DL3061.md): Invalid instruction order. Dockerfile must begin with `FROM`, `ARG` or comment. - [hadolint/DL4000](https://tally.wharflab.com/rules/hadolint/DL4000.md): MAINTAINER is deprecated. - [hadolint/DL4001](https://tally.wharflab.com/rules/hadolint/DL4001.md): Either use Wget or Curl but not both. - [hadolint/DL4003](https://tally.wharflab.com/rules/hadolint/DL4003.md): Multiple `CMD` instructions found. - [hadolint/DL4004](https://tally.wharflab.com/rules/hadolint/DL4004.md): Multiple `ENTRYPOINT` instructions found. - [hadolint/DL4005](https://tally.wharflab.com/rules/hadolint/DL4005.md): Use `SHELL` to change the default shell. - [hadolint/DL4006](https://tally.wharflab.com/rules/hadolint/DL4006.md): Set the `SHELL` option `-o pipefail` before `RUN` with a pipe in. - [Hadolint rules](https://tally.wharflab.com/rules/hadolint/overview.md): tally implements Hadolint DL rules natively and covers additional ones via equivalent BuildKit and tally rules. - [Rules overview](https://tally.wharflab.com/rules/overview.md): tally rules span four namespaces: tally/, buildkit/, hadolint/, and shellcheck/. Learn how to enable, disable, and suppress rules. - [shellcheck/SC1040](https://tally.wharflab.com/rules/shellcheck/SC1040.md): When using `<<-`, the heredoc terminator may only be indented with tabs. - [tally/circular-stage-deps](https://tally.wharflab.com/rules/tally/circular-stage-deps.md): Detects circular dependencies between build stages. - [tally/consistent-indentation](https://tally.wharflab.com/rules/tally/consistent-indentation.md): Enforces consistent indentation for Dockerfile build stages. - [tally/copy-after-user-without-chown](https://tally.wharflab.com/rules/tally/copy-after-user-without-chown.md): COPY/ADD without --chown after USER creates root-owned files. - [tally/copy-from-empty-scratch-stage](https://tally.wharflab.com/rules/tally/copy-from-empty-scratch-stage.md): Detects COPY --from referencing a scratch stage with no file-producing instructions. - [tally/curl-should-follow-redirects](https://tally.wharflab.com/rules/tally/curl-should-follow-redirects.md): curl commands should include `--location` (or `--follow`) to follow HTTP redirects. - [tally/eol-last](https://tally.wharflab.com/rules/tally/eol-last.md): Enforces a newline at the end of non-empty files. - [tally/epilogue-order](https://tally.wharflab.com/rules/tally/epilogue-order.md): Runtime-configuration instructions should appear at the end of each output stage in canonical order. - [tally/gpu/cuda-version-mismatch](https://tally.wharflab.com/rules/tally/gpu/cuda-version-mismatch.md): CUDA-specific pip/conda wheel version does not match the base image's CUDA toolkit. - [tally/gpu/no-buildtime-gpu-queries](https://tally.wharflab.com/rules/tally/gpu/no-buildtime-gpu-queries.md): GPU hardware is not available during `docker build`; runtime GPU queries in `RUN` will fail or return misleading results. - [tally/gpu/no-container-runtime-in-image](https://tally.wharflab.com/rules/tally/gpu/no-container-runtime-in-image.md): NVIDIA container runtime packages belong on the host, not inside the image. - [tally/gpu/no-hardcoded-visible-devices](https://tally.wharflab.com/rules/tally/gpu/no-hardcoded-visible-devices.md): GPU visibility is deployment policy; hardcoding it in the image reduces portability. - [tally/gpu/no-redundant-cuda-install](https://tally.wharflab.com/rules/tally/gpu/no-redundant-cuda-install.md): CUDA packages are already provided by the nvidia/cuda base image. - [tally/gpu/prefer-minimal-driver-capabilities](https://tally.wharflab.com/rules/tally/gpu/prefer-minimal-driver-capabilities.md): `NVIDIA_DRIVER_CAPABILITIES=all` exposes more driver surface than most workloads need; prefer a minimal capability set. - [tally/gpu/prefer-runtime-final-stage](https://tally.wharflab.com/rules/tally/gpu/prefer-runtime-final-stage.md): Final stage uses an NVIDIA devel image without clear build-time needs; prefer a runtime or base variant for the shipped stage. - [tally/gpu/prefer-uv-over-conda](https://tally.wharflab.com/rules/tally/gpu/prefer-uv-over-conda.md): Narrow GPU Python Dockerfiles can often be migrated from conda to uv for faster, lock-friendly installs. - [tally/invalid-json-form](https://tally.wharflab.com/rules/tally/invalid-json-form.md): Arguments appear to use JSON exec-form but contain invalid JSON. - [tally/invalid-onbuild-trigger](https://tally.wharflab.com/rules/tally/invalid-onbuild-trigger.md): ONBUILD trigger instruction is not a valid Dockerfile instruction. - [tally/labels/no-duplicate-keys](https://tally.wharflab.com/rules/tally/labels/no-duplicate-keys.md): LABEL keys should be set at most once per build stage. - [tally/labels/valid-key](https://tally.wharflab.com/rules/tally/labels/valid-key.md): LABEL keys should follow Docker's documented key format and avoid reserved Docker namespaces. - [tally/max-lines](https://tally.wharflab.com/rules/tally/max-lines.md): Enforces maximum number of lines in a Dockerfile. - [tally/named-identity-in-passwdless-stage](https://tally.wharflab.com/rules/tally/named-identity-in-passwdless-stage.md): Named user/group in USER or --chown requires /etc/passwd which passwd-less stages lack. - [tally/newline-between-instructions](https://tally.wharflab.com/rules/tally/newline-between-instructions.md): Controls blank lines between Dockerfile instructions. - [tally/newline-per-chained-call](https://tally.wharflab.com/rules/tally/newline-per-chained-call.md): Each chained element within an instruction should be on its own line. - [tally/no-multi-spaces](https://tally.wharflab.com/rules/tally/no-multi-spaces.md): Disallows multiple consecutive spaces within Dockerfile instructions. - [tally/no-multiple-empty-lines](https://tally.wharflab.com/rules/tally/no-multiple-empty-lines.md): Disallows multiple consecutive empty lines in Dockerfiles. - [tally/no-trailing-spaces](https://tally.wharflab.com/rules/tally/no-trailing-spaces.md): Disallows trailing whitespace at the end of lines. - [tally/no-ungraceful-stopsignal](https://tally.wharflab.com/rules/tally/no-ungraceful-stopsignal.md): STOPSIGNAL should not use signals that prevent graceful shutdown. - [tally/no-unreachable-stages](https://tally.wharflab.com/rules/tally/no-unreachable-stages.md): Warns about build stages that don't contribute to the final image. - [tally/php/composer-no-dev-in-production](https://tally.wharflab.com/rules/tally/php/composer-no-dev-in-production.md): Production Composer install commands should include `--no-dev`. - [tally/php/enable-opcache-in-production](https://tally.wharflab.com/rules/tally/php/enable-opcache-in-production.md): Production PHP web runtime images should install and enable OPcache. - [tally/php/no-xdebug-in-final-image](https://tally.wharflab.com/rules/tally/php/no-xdebug-in-final-image.md): Final image installs or enables Xdebug, a development-only tool. - [tally/platform-mismatch](https://tally.wharflab.com/rules/tally/platform-mismatch.md): Explicit `--platform` on FROM does not match what the registry provides. - [tally/powershell/error-action-preference](https://tally.wharflab.com/rules/tally/powershell/error-action-preference.md): Require `$ErrorActionPreference = 'Stop'` and `$PSNativeCommandUseErrorActionPreference = $true` in PowerShell RUN instructions. - [tally/powershell/prefer-shell-instruction](https://tally.wharflab.com/rules/tally/powershell/prefer-shell-instruction.md): Prefer a `SHELL` instruction over repeating `pwsh` or `powershell` wrappers in `RUN`. - [tally/powershell/progress-preference](https://tally.wharflab.com/rules/tally/powershell/progress-preference.md): Suppress PowerShell progress bars before `Invoke-WebRequest` by setting `$ProgressPreference = 'SilentlyContinue'`. - [tally/prefer-add-git](https://tally.wharflab.com/rules/tally/prefer-add-git.md): Prefer `ADD ` over `git clone` inside `RUN`. - [tally/prefer-add-unpack](https://tally.wharflab.com/rules/tally/prefer-add-unpack.md): Prefer `ADD --unpack` for downloading and extracting remote archives. - [tally/prefer-canonical-stopsignal](https://tally.wharflab.com/rules/tally/prefer-canonical-stopsignal.md): STOPSIGNAL should use canonical signal names for clarity and consistency. - [tally/prefer-copy-chmod](https://tally.wharflab.com/rules/tally/prefer-copy-chmod.md): Prefer `COPY --chmod` over a separate `COPY` followed by `RUN chmod`. - [tally/prefer-copy-heredoc](https://tally.wharflab.com/rules/tally/prefer-copy-heredoc.md): Suggests using COPY heredoc for file creation instead of RUN echo/cat. - [tally/prefer-curl-config](https://tally.wharflab.com/rules/tally/prefer-curl-config.md): Stages using curl should include a retry config to handle transient failures. - [tally/prefer-formatted-heredocs](https://tally.wharflab.com/rules/tally/prefer-formatted-heredocs.md): Pretty-print COPY and ADD heredocs for structured file types. - [`tally/prefer-multi-stage-build`](https://tally.wharflab.com/rules/tally/prefer-multi-stage-build.md): Suggests converting Dockerfiles that **build artifacts in a single stage** into a **multi-stage build** to reduce the final image size and avoid - [tally/prefer-nginx-sigquit](https://tally.wharflab.com/rules/tally/prefer-nginx-sigquit.md): nginx and openresty containers should use STOPSIGNAL SIGQUIT for graceful shutdown. - [tally/prefer-package-cache-mounts](https://tally.wharflab.com/rules/tally/prefer-package-cache-mounts.md): Suggests using BuildKit cache mounts for package-manager install/build commands. - [tally/prefer-run-heredoc](https://tally.wharflab.com/rules/tally/prefer-run-heredoc.md): Suggests using heredoc syntax for multi-command RUN instructions. - [tally/prefer-systemd-sigrtmin-plus-3](https://tally.wharflab.com/rules/tally/prefer-systemd-sigrtmin-plus-3.md): systemd/init containers should use STOPSIGNAL SIGRTMIN+3 for clean shutdown. - [tally/prefer-telemetry-opt-out](https://tally.wharflab.com/rules/tally/prefer-telemetry-opt-out.md): Stages using telemetry-enabled tools should set the vendor-documented opt-out environment variables. - [tally/prefer-vex-attestation](https://tally.wharflab.com/rules/tally/prefer-vex-attestation.md): Prefer attaching OpenVEX VEX documents as OCI attestations instead of copying `*.vex.json` into the image filesystem. - [tally/prefer-wget-config](https://tally.wharflab.com/rules/tally/prefer-wget-config.md): Stages using wget should include a retry config to handle transient failures. - [tally/require-secret-mounts](https://tally.wharflab.com/rules/tally/require-secret-mounts.md): Enforces `--mount=type=secret` on RUN instructions that execute commands requiring access to secrets — private registry credentials, API keys, cloud - [tally/require-stages](https://tally.wharflab.com/rules/tally/require-stages.md): Dockerfile has no stages to build. - [tally/secrets-in-code](https://tally.wharflab.com/rules/tally/secrets-in-code.md): Detects hardcoded secrets, API keys, and credentials using [gitleaks](https://github.com/gitleaks/gitleaks) patterns. - [tally/shell-run-in-scratch](https://tally.wharflab.com/rules/tally/shell-run-in-scratch.md): Detects shell-form RUN instructions in scratch stages where no shell exists. - [tally/sort-packages](https://tally.wharflab.com/rules/tally/sort-packages.md): Package lists in install commands should be sorted alphabetically. - [tally/stateful-root-runtime](https://tally.wharflab.com/rules/tally/stateful-root-runtime.md): Final stage runs as root and signals mutable/persistent state. - [tally/syntax-directive-typo](https://tally.wharflab.com/rules/tally/syntax-directive-typo.md): Detects typos in `# syntax=` parser directives. - [tally/unknown-instruction](https://tally.wharflab.com/rules/tally/unknown-instruction.md): Detects misspelled or invalid Dockerfile instruction keywords. - [tally/user-created-but-never-used](https://tally.wharflab.com/rules/tally/user-created-but-never-used.md): Final stage creates a user but never switches to it. - [tally/user-explicit-group-drops-supplementary-groups](https://tally.wharflab.com/rules/tally/user-explicit-group-drops-supplementary-groups.md): USER name:group silently drops supplementary groups established earlier in the Dockerfile. - [tally/windows/no-chown-flag](https://tally.wharflab.com/rules/tally/windows/no-chown-flag.md): `COPY --chown` and `ADD --chown` are silently ignored on Windows containers. - [tally/windows/no-run-mounts](https://tally.wharflab.com/rules/tally/windows/no-run-mounts.md): `RUN --mount` flags are not supported on Windows containers and will fail at runtime. - [tally/windows/no-stopsignal](https://tally.wharflab.com/rules/tally/windows/no-stopsignal.md): `STOPSIGNAL` has no effect on Windows containers because they do not support POSIX signals. - [tally/world-writable-state-path-workaround](https://tally.wharflab.com/rules/tally/world-writable-state-path-workaround.md): chmod 777/a+rwx sets world-writable permissions, a common ownership confusion workaround.