docker / compose

Define and run multi-container applications with Docker
https://docs.docker.com/compose/
Apache License 2.0
33.95k stars 5.22k forks source link

[BUG] '--no-deps' flag breaks dependencies between explicitly started services #10759

Closed IvanRibakov closed 2 weeks ago

IvanRibakov commented 1 year ago

Description

Since upgrading to Docker Compose 2.19.0 from 2.17.0 --no-deps flag behaviour seems to have changed.

Given following 2 services:

services:
  service-a:
    image: alpine
    command: ["sh", "-c", "sleep 10s && touch /tmp/healthy.txt && echo 'Hello from Service A' && tail -f /dev/null"]
    healthcheck:
      test: ls /tmp/healthy.txt
      interval: 2s
      timeout: 5s
      retries: 50

  service-b:
    image: alpine
    command: echo "Hello from Service B"
    depends_on:
      service-a: {condition: service_healthy}

Current behavior

Scenario 1: only service B is started

Then service B is started without launching service A:

$ docker compose up --no-deps --abort-on-container-exit service-b
[+] Running 1/0
 ✔ Container compose-deps-test-service-b-1  Created                                                                                                                                                                                                                                                                     0.0s 
Attaching to compose-deps-test-service-b-1
compose-deps-test-service-b-1  | Hello from Service B
compose-deps-test-service-b-1 exited with code 0
Aborting on container exit...
[+] Stopping 1/0
 ✔ Container compose-deps-test-service-b-1  Stopped

Scenario 2: both service A and B are started explicitly

Then service B is started without waiting for service A:

$ docker compose up --no-deps --abort-on-container-exit service-a service-b
[+] Running 2/0
 ✔ Container compose-deps-test-service-b-1  Created                                                                                                                                                                                                                                                                     0.0s 
 ✔ Container compose-deps-test-service-a-1  Created                                                                                                                                                                                                                                                                     0.0s 
Attaching to compose-deps-test-service-a-1, compose-deps-test-service-b-1
compose-deps-test-service-b-1  | Hello from Service B
compose-deps-test-service-b-1 exited with code 0
Aborting on container exit...
[+] Stopping 2/2
 ✔ Container compose-deps-test-service-b-1  Stopped                                                                                                                                                                                                                                                                     0.0s 
 ✔ Container compose-deps-test-service-a-1  Stopped

Expected behavior

Scenario 1: only service B is started

Expecting current behaviour (no changes)

Scenario 2: both service A and B are started explicitly

Expecting service B to wait for service A to become healthy as defined in the depends_on configuration object. This was the behaviour in earlier versions of Docker Compose.

Steps To Reproduce

  1. Create docker-compose.yml file as defined above
  2. For scenario 1 execute: docker compose up --no-deps --abort-on-container-exit service-b
  3. For scenario 2 execute: docker compose up --no-deps --abort-on-container-exit service-a service-b

Compose Version

$ docker compose version
Docker Compose version v2.19.0
$ docker-compose version
Command 'docker-compose' not found, but can be installed with:
sudo apt install docker-compose

### Docker Environment

```Text
$ docker info
Client: Docker Engine - Community
 Version:    24.0.2
 Context:    desktop-linux
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.11.0
    Path:     /usr/lib/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.19.0
    Path:     /usr/lib/docker/cli-plugins/docker-compose
  dev: Docker Dev Environments (Docker Inc.)
    Version:  v0.1.0
    Path:     /usr/lib/docker/cli-plugins/docker-dev
  extension: Manages Docker extensions (Docker Inc.)
    Version:  v0.2.20
    Path:     /usr/lib/docker/cli-plugins/docker-extension
  init: Creates Docker-related starter files for your project (Docker Inc.)
    Version:  v0.1.0-beta.6
    Path:     /usr/lib/docker/cli-plugins/docker-init
  sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
    Version:  0.6.0
    Path:     /usr/lib/docker/cli-plugins/docker-sbom
  scan: Docker Scan (Docker Inc.)
    Version:  v0.26.0
    Path:     /usr/lib/docker/cli-plugins/docker-scan
  scout: Command line tool for Docker Scout (Docker Inc.)
    Version:  0.16.1
    Path:     /usr/lib/docker/cli-plugins/docker-scout

Server:
 Containers: 3
  Running: 0
  Paused: 0
  Stopped: 3
 Images: 1
 Server Version: 24.0.2
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 3dce8eb055cbb6872793272b4f20ed16117344f8
 runc version: v1.1.7-0-g860f061
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 5.15.49-linuxkit-pr
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 7.674GiB
 Name: docker-desktop
 ID: 48eb5da3-d9de-4e88-8b6b-5ad6249b9788
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 No Proxy: hubproxy.docker.internal
 Experimental: false
 Insecure Registries:
  hubproxy.docker.internal:5555
  127.0.0.0/8
 Live Restore Enabled: false

Anything else?

No response

IvanRibakov commented 1 year ago

My understanding of the issue is that at the moment --no-deps flag controls both:

  1. starting of dependency services
  2. validating that dependency services satisfy configured conditions

In reality, it is useful to separate the 2 behaviours. For example, I'm using a docker compose with 3+ services to perform system tests. When debugging issues I want to be able to disable one of the services (using --no-deps + explicitly listing services I want to run) and substitute the disabled service with an already running container with debug tools set up. This was working fine until upgrading to 2.19.0.

Ideal solution - introduce new flags --no-deps-start. If set, will ensure that configured dependencies will not be used to launch any services, only the services explicitly listed in the up command arguments will be started. But the validation of conditions of any dependencies between services that are listed in the up command arguments or are already running will still be performed.

IvanRibakov commented 1 year ago

@milas sorry to tag you directly, just wanted to ask what does the removal of the status/0-triage badge mean for the issue?

ndeloof commented 1 year ago

As you enabled --no-deps depends_on support is just disabled, and obviously dependency between A and B is then ignored. Seems to me this reflects lack of separation between your services that would deserve more independent compose files being used to isolate subsets of your architecture. Anyway, in the meantime you could rely on https://github.com/compose-spec/compose-spec/commit/78b22da5f5c8998fde4c7434f19f3f4d01cde648 to be supported in next release

IvanRibakov commented 1 year ago

and obviously dependency between A and B is then ignored.

Not so obvious since behaviour was different until compose version 2.18.0 or 2.19.0. And I did not find any mention of related changes in the changelog so the change in behaviour indeed caught me by surprise.

Seems to me this reflects lack of separation between your services that would deserve more independent compose files being used to isolate subsets of your architecture.

Service architecture is already pretty minimal:

The only further separation possible here is to manage 2 services completely independently but that negates all orchestration benefits obtained from using compose.

in the meantime you could rely on https://github.com/compose-spec/compose-spec/commit/78b22da5f5c8998fde4c7434f19f3f4d01cde648 to be supported in next release

required: when false Compose only warns you when the dependency service isn't started or available.

I'm not sure that will help in my case since what I'm trying to do is essentially completely substitute service A with a standalone custom container (substitution is done at the network layer by starting standalone container on the same address as the service A would be running on). Or am I misunderstanding the behaviour of the new required feature?

What about the point raised earlier about a more granular dependency control?

  • starting of dependency services
  • validating that dependency services satisfy configured conditions

Does that have any future at all?

IvanRibakov commented 1 year ago

Are there any plans to restore the old behaviour of the --no-deps flag that allowed starting a subset of service and still respect their healthcheck-based dependencies?

github-actions[bot] commented 1 month ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 weeks ago

This issue has been automatically marked as not stale anymore due to the recent activity.

stale[bot] commented 3 weeks ago

This issue has been automatically marked as not stale anymore due to the recent activity.

ndeloof commented 2 weeks ago

Closing as "not planned". no-deps disables dependency management, as name suggests. This behavior looks sane to us and predictable for users. If you have a real-world example which require a distinct behavior, please create a follow-up issue