How to avoid service dependencies from being stopped in Docker Compose?

Viewed 690

Given the following Docker Compose file....

version: '3.8'

services:
  producer:
    image: producer
    container_name: producer
    depends_on: [db]
    build:
      context: ./producer
      dockerfile: ./Dockerfile

  db:
    image: some-db-image
    container_name: db

When I do docker-compose up producer obviously the db service gets started too. When I CTRL+C both services are stopped. This is expected and fine.

But sometimes, the db service is started before, on a different shell and so doing docker-compose up producer understands that db is running and only starts producer. But when I hit CTRL+C, both producer and db are stopped even though db was not started as part of this docker compose up command.

Is there a way to avoid getting the dependencies services stopped when stopping its "parent" ?

5 Answers

When running just docker-compose up, the CTRL+C command always stops all running services in the current compose scope. It doesn't care about depends_on.

You would need to spin it up with detach option -d, like

docker-compose up -d producer

Then you can do

docker stop producer

And db service should still be running.

As I understand your question: You want to stop a container A which depends on another container B. But when stopping A, you don't want docker-compose to stop B.

Docker-compose stops the dependent containers ('B' in this case) when 'A' is stopped.

How I would approach this:

  1. Split up the docker-compose files into A and B
  2. In docker-compose for A create a health check testing (and waiting) for container B to be alive. Since this is a database, you could do this with a dummy query.

Then you still have dependency, but not the docker-compose connection of stopping dependant containers.

You can't simply do that with CTRL+C.

Your docker-compose file and the services defined in it are treated as a project. You may notice that all containers, networks and volumes are prefixed with the name of the directory where the docker-compose file is located by default. This is the project name. It can be changed via an environment variable or the -p flag of the docker-compose command. What docker-compose does is it keeps track of all the resources for a given project.

In your case there are two services: db and producer. Whenever you run docker-compose up, both of them start up. They both end up being part of the same project. The same applies when you only start one of the services (e.g. with docker-compose up db). You can later start the other service and it will still be part of the same project.

One more thing to note here: Whenever you run docker-compose without the -d (detached) flag, you get attached to the whole project, meaning whenever you hit CTRL+C, you'll stop all services. It does not matter if the last compose command started only one of the services or if they depend on each other. Attaching to the project and hitting CTRL+C will stop them.

A possible solution to your problem would be the following: Start up your services via docker-compose up -d (both db and producer will get created). They are now in detached mode. If you still want to check the logs in real time (kinda like attaching), use docker-compose logs -f. Now, however, if you want to stop only one of the services you can simply do docker-compose stop $SVC_NAME (where $SVC_NAME is either db or producer) and this will keep the other one running. This way, whatever happens to your terminal session, your services won't stop, unless you explicitly tell them to.

Is there a way to avoid getting the dependencies services stopped when stopping its "parent" ?

Yes. Using the new version docker compose instead of docker-compose might solve your problem Reference.

Simple example

Assuming now you are using the new version, your process could be something like this.

docker-compose.yml

version: "3.8"
services:
  db:
    build: .
  producer:
    build: .
    depends_on: [db]
  extra:
    build: .

Dockerfile

FROM node:alpine
WORKDIR /app
COPY . .
ENTRYPOINT [ "/bin/sh", "script.sh" ]

script.sh

while :; do sleep 1; done

Suppose db has started before with
$ docker compose up -d db.
Then later,
$ docker compose up -d producer.
Now you can stop only producer with
$ docker compose stop producer. You can check if db is still running with
$ docker compose ps.

Notice the use of -d flag for detached mode, as pointed out in another answer, so you don't need to kill the process with CTRL+C. Also, using detached flag allows you to check the services that are running with docker compose ps.

A similar issue as yours was reported and fixed a while ago, as you can see here.

I was not able to reproduce the behavior you observe with a complete minimal example. Namely, when running docker compose stop producer, the underlying db is not stopped AFAICT.

Anyway, you may be interested in an alternative command that is a bit more flexible than docker compose up, regarding how to run "one-off commands": docker compose run.

The typical use cases are as follows:

  • docker compose run db bash → run the db service, replacing the default CMD with bash
  • docker compose run -d db → run the db service in the background (detach mode)
  • docker compose run --service-ports producer → run the service producer and its dependencies (unless they were run with docker compose up), enabling the ports mapping.

So for your specific use case, you could run:

docker compose up -d db

docker compose run --service-ports producer
Related