Detach pending during container health check

Hey there

I recently noticed a small but annoying issue. When I run docker compose up and it gets to the health check, if I try to detach, docker compose doesn’t give me control and waits for the health check to finish. I thought it would be cool to try fixing this. What do you think?

OS: Arch Linux | x86_64

➜  ~ docker compose version
Docker Compose version 5.1.1
➜  ~ docker -v
Docker version 29.3.1, build c2be9ccfc3

Do you really run docker-compose up or docker compose up? When you shared the version, you used docker compose version with the space not with the dash. Or is docker-compose set as an alias to docker compose on your machine like when Docker Desktop is installed?

Do you run Docke Desktop or Docker CE?

Note that neither Docker Desktop nor Docker CE is supported on Arch by Docker directly. I’m not saying it wouldn’t happen on other systems. but it would be nice if someone could reproduce the issue on supported systems.

Just to speed things up and make sure we don’t try something else, can you create a small compose file to reproduce the issue, so we can test on our machines?

Nice catch.
docker-compose was a typo. I’ve already edited the post.
I use Docker CE.

here’s file to reproduce

services:
  persistence:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: postgres
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"]
      interval: 15s
      timeout: 15s
      retries: 5

  linux:
    image: alpine:latest
    command: ["sh", "-c", "echo started after db && sleep 1000"]
    depends_on:
      persistence:
        condition: service_healthy

Thanks for the compose file. I can confirm, it happens with Docker Desktop for Mac as well.

When I use docker compose up -d, I get the prompt back only after all the services are started. Including the “linux” service, which depends on the health of the “persistence” service. And it looks like the when I run attached mode and try to detach after that as you tried, compose still waits until all the services are running before you can detach and get the prompt back.

I see you already reported it on GitHub, so we will see what the developers can say about it

Hmm. Looks like backend.Up() being a blocking call in runUp() in cmd/compose/up.go. In attached mode it handles both log streaming and waiting for services to reach their desired state, but “d” only stops log attacchment, but the main goroutine is still blocked inside Up()

That could be true, but I was thinking about it and I don’t think it could be “fixed”. The best I can imagine is adding some notification to the terminal after pressing “d” so it is clear that compose is still working on something and waiting for a service to start.

Docker Compose is a client tool for Docker, so if we configure a health check and depends_on condition telling compose that it should wait with one service until another starts and healthy, it has to remain in the foreground because there is nothing in the background to finish that task. There is no dependency handling in the Docker Daemon. Maybe Docker Compose could give the terminal back by doing everything in the background, but if any error occurs, you would have no logs about what happened. Unless a new option is also introduced that saves a log file where you ran the command.

I don’t know, but the solution is not obvious to me.