Skip to main content
HEALTHCHECK instruction missing.
PropertyValue
SeverityIgnore (off by default)
CategoryBest Practice
DefaultOff

Description

This is an optional rule. When it is required to define a health check (e.g. by company policy), it must not be omitted. This rule is disabled by default because a HEALTHCHECK is not desirable in all circumstances. Images used with Kubernetes do not benefit from a HEALTHCHECK instruction, as Kubernetes brings its own mechanisms.

Examples

Problematic code

FROM busybox

Correct code

FROM busybox
HEALTHCHECK CMD /bin/health
or:
FROM busybox
HEALTHCHECK NONE

tally enhancements

Smart suppression

tally automatically suppresses this rule when the Dockerfile shows strong signals that a HEALTHCHECK would not be beneficial:

Serverless / FaaS base images

Containers built for serverless platforms have their lifecycle managed externally — the platform decides when to start, stop, and replace function instances. A container-level HEALTHCHECK is ignored in these environments.
PlatformSuppressed image patterns
AWS Lambdapublic.ecr.aws/lambda/*, gallery.ecr.aws/lambda/*, amazon/aws-lambda-*
Azure Functionsmcr.microsoft.com/azure-functions/*
OpenFaaSopenfaas/of-watchdog, openfaas/classic-watchdog (including ghcr.io variants)
If any stage in the Dockerfile uses a recognized serverless base image, the violation is suppressed for the entire file. Multi-stage builds that pull from a Lambda image in one stage and copy artifacts into another are still covered because the presence of the serverless image signals the target runtime.

Serverless framework entrypoints

When the final stage’s CMD or ENTRYPOINT invokes a known serverless function framework, the container is a short-lived function handler managed by the platform — not a service that benefits from HEALTHCHECK.
FrameworkExample
Google Cloud Functions (functions-framework)CMD ["functions-framework", "--target=hello"]
The exec prefix commonly used in shell form is handled:
CMD exec functions-framework --target=hello --port=$PORT

Interactive / shell-only containers

When the final stage’s CMD or ENTRYPOINT resolves to a bare interactive shell (sh, bash, zsh, ash, dash, fish, csh, tcsh, ksh), the container is clearly not a long-running service — there is no endpoint to health-check. Recognized patterns:
CMD ["bash"]               # exec form
CMD bash                   # shell form
CMD ["bash", "-l"]         # shell with flags (still interactive)
ENTRYPOINT ["/bin/sh"]     # entrypoint shell
Not suppressed when the shell is used to execute a command:
CMD ["bash", "-c", "my-app"]   # runs my-app, not interactive
If an ENTRYPOINT is present, it takes precedence over CMD (matching Docker runtime semantics).

No explicit CMD/ENTRYPOINT (external parent delegation)

When the final stage has no CMD or ENTRYPOINT instruction and its base is an external image (not another build stage), the image delegates run orchestration to its parent. In these cases the parent likely also defines a HEALTHCHECK, so flagging the child produces false positives. The violation is suppressed.
FROM nginx:latest
RUN echo "custom config" > /etc/nginx/conf.d/default.conf
EXPOSE 80
# No CMD — nginx base image provides CMD and likely HEALTHCHECK
This does not apply when the final stage inherits from a prior build stage (FROM <stage-name>), because CMD/ENTRYPOINT are inherited from the prior stage and the image is not opaque:
FROM alpine AS base
CMD ["my-app"]
FROM base
RUN echo "setup"
# DL3057 still fires — CMD inherited from "base", image is not opaque

Explicit opt-out with HEALTHCHECK NONE

HEALTHCHECK NONE is treated as a deliberate opt-out. When present in any stage, DL3057 is fully suppressed — no fast-path violation is emitted and no async registry checks are planned. This matches Docker’s semantics where HEALTHCHECK NONE explicitly disables health checking.

Async registry resolution

tally extends this rule with async registry resolution (enabled with --slow-checks):
  • Base image inspection: For each external base image, tally checks if it already defines a HEALTHCHECK in its image metadata. If so, the violation is suppressed since the health check is inherited. This check is skipped when any explicit HEALTHCHECK instruction (CMD or NONE) is already present.
  • Cross-rule awareness: buildkit/MultipleInstructionsDisallowed may still flag duplicate HEALTHCHECK instructions even when DL3057 is suppressed.

Reference