-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
Description
When docker compose up is run interactively from a shell, then pressing Ctrl+C (which sends a SIGINT signal to the Docker process) will have the same effect as if I run docker compose stop on the same config file from another terminal - the containers will be gracefully stopped and then the docker compose up command will exit.
When I run the same command in a background process using external means (e.g. Bash job control) and send a SIGINT to the process, it is ignored on the first and second try, and then on the third try I'll get an error and a forced shutdown.
I believe this to be inconsistent behaviour - a SIGINT is a SIGINT, and the process should react to it the same regardless of whether it's running interactively or not. This behaviour causes issues with running parallel jobs, when some jobs are outside of Docker. I know I can run the Compose in detached mode, but that has other issues - like prefixing and interleaving output from the parallel jobs on the same terminal, which is easy with job control.
Steps To Reproduce
Reproduce using two files:
docker-compose.yml:
services:
nginx:
image: 'nginx:alpine'
restart: always
ports:
- '8000:80'test.sh:
#!/usr/bin/env bash
docker compose up &
jobs -l
waitInteractive
- Running
docker compose upwill correctly start the container - Pressing Ctrl+C will correctly stop the container and exit the previous command
Non-interactive
- Running
./test.shwill correctly start the container; the first line of output should include thedockerprocess's PID - Sending a SIGINT to said PID will NOT work - the signal will be ignored the first two times, and the third time will throw an error instead
Compose Version
Docker Compose version v2.20.2-desktop.1
Docker Environment
Client:
Version: 24.0.5
Context: desktop-linux
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.11.2-desktop.1
Path: /Users/danik/.docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.20.2-desktop.1
Path: /Users/danik/.docker/cli-plugins/docker-compose
dev: Docker Dev Environments (Docker Inc.)
Version: v0.1.0
Path: /Users/danik/.docker/cli-plugins/docker-dev
extension: Manages Docker extensions (Docker Inc.)
Version: v0.2.20
Path: /Users/danik/.docker/cli-plugins/docker-extension
init: Creates Docker-related starter files for your project (Docker Inc.)
Version: v0.1.0-beta.6
Path: /Users/danik/.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: /Users/danik/.docker/cli-plugins/docker-sbom
scan: Docker Scan (Docker Inc.)
Version: v0.26.0
Path: /Users/danik/.docker/cli-plugins/docker-scan
scout: Command line tool for Docker Scout (Docker Inc.)
Version: 0.20.0
Path: /Users/danik/.docker/cli-plugins/docker-scout
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 9
Server Version: 24.0.5
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: unconfined
cgroupns
Kernel Version: 5.15.49-linuxkit-pr
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.773GiB
Name: docker-desktop
ID: 8b8aa798-9fbe-4cc9-8ab9-39db14fe4843
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?
I haven't tested this extensively, but it appears that SIGTERM also doesn't terminate the running command; this, along with information I've read elsewhere, leads me to believe that the SIGINT handling in an interactive shell is actually the special case. I think I've read somewhere that Docker typically forwards all signals to the main process of the container and lets it handle the signal however it wants; while I think that's probably the most suitable approach for things like docker run and docker exec, in a Compose context it isn't obvious to me what will happen - will all the running services receive the signal? It would make much more sense to me if Docker had standard responses to standard signals in this scenario - ie. SIGINT and SIGTERM should both cause a graceful exit, which I understand as the equivalent of a docker compose stop. But I'm a small-time Docker user, I prefer running things directly, so I don't know much about all the various use-cases there might be.