containers / containers/podman-compose
up --wait does not fail when a service becomes unhealthy
- Dominant language
- Python
- Stars
- 6.2k
- Forks
- 622
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
`podman-compose up --wait` does not fail when a service becomes unhealthy.
When a service uses `depends_on` with `condition: service_healthy`, `up --wait` continues waiting after the dependency has become unhealthy. This wait can also continue beyond `--wait-timeout`.
Without the dependency, `--wait-timeout` ends the wait but returns status `0` even though the service remains unhealthy.
Docker Compose reports an error when a required service becomes unhealthy. `podman-compose` should provide compatible behavior so that CI and scripts neither hang nor report false success.
**To Reproduce**
Create a directory for the reproducer:
```sh
mkdir -p /tmp/podman-compose-unhealthy-repro
cd /tmp/podman-compose-unhealthy-repro
```
Create `compose.yaml`:
```yaml
services:
dependency:
image: busybox:latest
command: ["sh", "-c", "while :; do sleep 3600; done"]
healthcheck:
test: ["CMD-SHELL", "exit 1"]
interval: 1s
timeout: 1s
retries: 1
app:
image: busybox:latest
command: ["sh", "-c", "while :; do sleep 3600; done"]
depends_on:
dependency:
condition: service_healthy
```
The commands below explicitly use `unhealthy-repro` as the Compose project name:
```sh
timeout 10s podman-compose -p unhealthy-repro \
up -d --wait --wait-timeout 3
printf 'exit status: %s\n' "$?"
```
Inspect the containers:
```sh
podman ps -a \
--filter label=com.docker.compose.project=unhealthy-repro \
--format '{{.Names}} {{.Status}}'
```
Clean up:
```sh
podman-compose -p unhealthy-repro down
```
**Expected behavior**
As soon as `dependency` becomes unhealthy:
- `podman-compose up -d --wait` should stop waiting.
- The command should return a non-zero status.
- `app` should not be treated as ready.
- `--wait-timeout` should bound all readiness waits, including `service_healthy` dependency waits.
This matches the behavior of Docker Compose.
**Actual behavior**
The dependency becomes unhealthy, but `podman-compose` continues waiting.
The external `timeout` command eventually terminates `podman-compose`:
```text
exit status: 124
```
`--wait-timeout 3` does not bound this dependency wait.
As a related case, if the `app` service is removed so that only the unhealthy service remains, this command returns status `0` after the timeout even though the service is still unhealthy:
```sh
podman-compose -p unhealthy-repro up -d --wait --wait-timeout 3
```
**Output**
```text
$ podman-compose version
podman-compose version 1.6.0
$ podman --version
podman version 4.9.3
```
**Environment:**
- OS: Ubuntu 24.04
- Podman: 4.9.3, rootless
- podman-compose: 1.6.0
**Additional context**
In podman-compose 1.6.0, the readiness code waits for the `healthy` condition but does not appear to treat `unhealthy` as a failure:
https://github.com/containers/podman-compose/blob/v1.6.0/podman_compose.py#L3493-L3535
The `service_healthy` dependency wait also does not appear to be covered by `--wait-timeout`:
https://github.com/containers/podman-compose/blob/v1.6.0/podman_compose.py#L3685-L3730
Docker Compose explicitly reports an error when a service becomes unhealthy:
https://github.com/docker/compose/blob/main/pkg/compose/convergence.go
A possible fix would be to:
1. Wait for both `healthy` and terminal failure states such as `unhealthy`.
2. Return a non-zero status immediately when a required service becomes unhealthy.
3. Apply `--wait-timeout` to dependency-condition waits as well as the final readiness wait.
Contributor guide
Research direction
Read podman_compose.py lines 3493-3535 and 3685-3730, focusing on readiness handling and service_healthy dependency waits. Run the supplied compose.yaml reproducer with --wait and --wait-timeout. Done means unhealthy required services stop waiting promptly, return non-zero, and all readiness waits respect the timeout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker-compose, python
- Domain
- cli, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100