containers / containers/podman-compose

healthcheck.start_interval is ineffective and incorrectly mapped to --health-startup-interval

Open
#1,500 2 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Python
Stars
6.2k
Forks
622
PR merge metrics
No merged PRs in 30d

Description

**Describe the bug**

`podman-compose` accepts the Compose Specification field
`healthcheck.start_interval`, but it does not cause health checks to run at
that interval during `healthcheck.start_period`.

The current implementation maps:

```yaml
healthcheck:
start_interval: 1s
```

to:

```text
--health-startup-interval 1s
```

Source:

https://github.com/containers/podman-compose/blob/8156ab4bc9fc90a10f81242c81136155973e165a/podman_compose.py#L1534-L1542

However, Podman's `--health-startup-interval` belongs to [Podman's separate
startup-healthcheck mechanism](https://github.com/podman-container-tools/podman/blob/v6.0.1/docs/source/markdown/podman-healthcheck.1.md#startup-healthcheck-vs-regular-healthcheck).
That mechanism is gated by `--health-startup-cmd`.
`podman-compose` generates `--health-cmd`, but does
not generate `--health-startup-cmd`, so the startup interval does not create
or affect a startup healthcheck.

More importantly, the two settings have different semantics:

- Compose `start_interval` changes the interval of the regular healthcheck
during `start_period`.
- Podman `--health-startup-interval` controls a separate startup healthcheck,
which stops after its configured success condition is met.
- Podman's startup healthcheck is not bounded by `--health-start-period`.

Therefore, mapping `start_interval` to `--health-startup-interval` is not
equivalent to the Compose Specification, even if an
`--health-startup-cmd` were also generated.

This mapping was introduced as support for `start_interval` in #1271. The
current unit test verifies the generated CLI argument, but does not verify
the resulting healthcheck schedule:

https://github.com/containers/podman-compose/blob/8156ab4bc9fc90a10f81242c81136155973e165a/tests/unit/test_container_to_args.py#L1165-L1197

This is partly related to a missing Podman runtime feature, but the
`podman-compose`-specific bug is that it accepts the Compose field and
silently translates it to a different and ineffective Podman option.

**To Reproduce**

1. Create a directory containing only this `compose.yaml`:

```yaml
services:
test:
image: docker.io/library/busybox:latest
container_name: health-start-interval-repro
command: ["sh", "-c", "sleep 120"]
healthcheck:
test:
- CMD-SHELL
- "date +%s >> /tmp/healthcheck-times; exit 1"
interval: 30s
timeout: 2s
retries: 100
start_period: 10s
start_interval: 1s
```

The healthcheck always fails and records each execution time inside the
container. It intentionally keeps failing so that it remains in the startup
period for the full 10 seconds.

2. Run:

```console
$ podman-compose up -d
$ sleep 12
$ podman exec health-start-interval-repro \
sh -c 'cat /tmp/healthcheck-times; printf "count="; wc -l < /tmp/healthcheck-times'
```

3. Clean up:

```console
$ podman-compose down
```

**Expected behavior**

According to the Compose Specification, the regular healthcheck should run
approximately every second during the 10-second `start_period`. After the
startup period, it should run every 30 seconds.

The output after 12 seconds should therefore contain approximately 10 health
check timestamps.

If the installed Podman version cannot implement Compose
`healthcheck.start_interval`, `podman-compose` should report the field as
unsupported with an explicit warning or error.

Compose Specification:

https://github.com/compose-spec/compose-spec/blob/main/spec.md#healthcheck

**Actual behavior**

The healthcheck does not run every second during `start_period`. On my
system, the output was:

```text
1784066724
count=1
```

The checks follow the normal `interval` instead. The generated
`--health-startup-interval` has no effect because no Podman startup
healthcheck command is configured.

**Output**

```console
$ podman-compose version
podman-compose version 1.6.0
podman version 4.9.3

$ podman-compose up -d
d5550213217795690767e832a32565298d1ecf552b5398c27686d170065fc642
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob b05093807bb0 done |
Copying config c6348fa86b done |
Writing manifest to image destination
c3754f331c11e41b810a8a290f1a10bb4eabaac3077f46dff97ea122a2e31da5
health-start-interval-repro
$ sleep 12
$ podman exec health-start-interval-repro \
sh -c 'cat /tmp/healthcheck-times; printf "count="; wc -l < /tmp/healthcheck-times'
1784066724
count=1
$ podman-compose down
health-start-interval-repro
health-start-interval-repro
d5550213217795690767e832a32565298d1ecf552b5398c27686d170065fc642
pc_test_default
```

**Environment:**

- OS: WSL
- Podman version: 4.9.3
- podman-compose version: 1.6.0

**Additional context**

Podman documents `--health-startup-cmd` and
`--health-startup-interval` as a separate startup-healthcheck mechanism:

https://github.com/podman-container-tools/podman/blob/v6.0.1/docs/source/markdown/podman-healthcheck.1.md#startup-healthcheck-vs-regular-healthcheck

Podman's regular `--health-start-period` documentation states that checks
continue to use `--health-interval`:

https://docs.podman.io/en/latest/markdown/podman-run.1.html

The missing Docker-compatible `start_interval` functionality in Podman itself
is tracked separately in:

https://github.com/podman-container-tools/podman/issues/26505

A possible `podman-compose` resolution would be:

1. Stop translating Compose `start_interval` to
`--health-startup-interval`, because the semantics are different.
2. Until Podman provides an exact equivalent, emit an explicit unsupported
warning or error.
3. Once Podman supports the field, map it to the corresponding native
option/API field.
4. (Optional) Add an integration test that verifies the actual execution timestamps,
rather than only checking the generated CLI arguments.

Contributor guide

Open the contributing guide

Research direction

Start in podman_compose.py at lines 1534-1542 and inspect tests/unit/test_container_to_args.py around lines 1165-1197. Compare the generated arguments with Podman’s regular and startup healthcheck semantics, then run the unit test and the documented BusyBox reproduction. Done means the Compose field is not silently mapped to an incompatible option and its supported or unsupported behavior is covered by tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, devops, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.