> ## Documentation Index
> Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# hadolint/DL3057

> `HEALTHCHECK` instruction missing.

`HEALTHCHECK` instruction missing.

| Property | Value                   |
| -------- | ----------------------- |
| Severity | Ignore (off by default) |
| Category | Best Practice           |
| Default  | Off                     |

## 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

```dockerfile theme={null}
FROM busybox
```

### Correct code

```dockerfile theme={null}
FROM busybox
HEALTHCHECK CMD /bin/health
```

or:

```dockerfile theme={null}
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.

| Platform            | Suppressed image patterns                                                          |
| ------------------- | ---------------------------------------------------------------------------------- |
| **AWS Lambda**      | `public.ecr.aws/lambda/*`, `gallery.ecr.aws/lambda/*`, `amazon/aws-lambda-*`       |
| **Azure Functions** | `mcr.microsoft.com/azure-functions/*`                                              |
| **OpenFaaS**        | `openfaas/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`.

| Framework                                          | Example                                         |
| -------------------------------------------------- | ----------------------------------------------- |
| **Google Cloud Functions** (`functions-framework`) | `CMD ["functions-framework", "--target=hello"]` |

The `exec` prefix commonly used in shell form is handled:

```dockerfile theme={null}
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:

```dockerfile theme={null}
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:

```dockerfile theme={null}
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.

```dockerfile theme={null}
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:

```dockerfile theme={null}
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

* [hadolint/DL3057](https://github.com/hadolint/hadolint/wiki/DL3057)
