moby: Kill `docker exec` command will not terminate the spawned process
Whenever a process is launched via docker exec
, it seems that killing docker exec
will not terminate the process. For example:
> docker run -d --name test-exec busybox top
> docker exec -it test-exec sh
/ # # we have an exec shell now. assume pid of docker exec is 1234
> kill 1234
# docker exec process is terminated atm, but `nsenter-exec` process is still running with sh as its child
I would expect that killing docker exec -it
process will also kill the spawned process, or there should be a way to stop the spawn process similar to how docker stop
works.
My version of docker:
❯ docker version
Client version: 1.3.1-dev
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): c049949
OS/Arch (client): linux/amd64
Server version: 1.3.1-dev
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): c049949
❯ docker info
Containers: 1
Images: 681
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Dirs: 693
Execution Driver: native-0.2
Kernel Version: 3.13.0-33-generic
Operating System: Ubuntu 14.04.1 LTS
CPUs: 2
Total Memory: 1.955 GiB
Debug mode (server): true
Debug mode (client): false
Fds: 17
Goroutines: 16
EventsListeners: 0
Init Path: /home/action/bin/docker
Username: dqminh
Registry: [https://index.docker.io/v1/]
WARNING: No swap limit support
About this issue
- Original URL
- State: open
- Created 10 years ago
- Reactions: 42
- Comments: 66 (27 by maintainers)
Links to this issue
Commits related to this issue
- [proxy] We can only rely on receiving a signal when we are a container Due to https://github.com/docker/docker/issues/9098, there is no way to signal an exec. Instead we'll have to just poll the inte... — committed to paulbellamy/weave by paulbellamy 9 years ago
- [proxy] We can only rely on receiving a signal when we are a container Due to https://github.com/docker/docker/issues/9098, there is no way to signal an exec. Instead we'll have to just poll the inte... — committed to paulbellamy/weave by paulbellamy 9 years ago
- [proxy] We can only rely on receiving a signal when we are a container Due to https://github.com/docker/docker/issues/9098, there is no way to signal an exec. Instead we'll have to just poll the inte... — committed to paulbellamy/weave by paulbellamy 9 years ago
- Enable sig-proxy by default in run and attach — committed to moby/moby by vieux 11 years ago
- Fix "docker exec" orphan process When this "dockersh" process is signalled/killed (like when ssh disconnects due to network issue etc), due to a docker bug, processes that are running inside 'docker ... — committed to freshworks/dockersh by surki 5 years ago
- Fix "docker exec" orphan process When this "dockersh" process is signalled/killed (like when ssh disconnects due to network issue etc), due to a docker bug, processes that are running inside 'docker ... — committed to freshworks/dockersh by surki 5 years ago
- Fix "docker exec" orphan process When this "dockersh" process is signalled/killed (like when ssh disconnects due to network issue etc), due to a docker bug, processes that are running inside 'docker ... — committed to freshworks/dockersh by surki 5 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-clickhouse by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-couchdb by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-elasticsearch by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-graphite by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-mariadb by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-memcached by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-mongo by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-mysql by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-nats by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-omnisci by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-postgres by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-pushpin by josegonzalez 3 years ago
- docs: document the possibility of zombie processes on ssh disconnect for :connect and :enter commands Apparently terminating the ssh connection that runs 'docker exec' may result in a process leak as... — committed to dokku/dokku-rabbitmq by josegonzalez 3 years ago
Yo, 2017! Any love?
Is there any movement on this? We’ve just hit this issue as well - very unexpected behavior.
This issue was the root cause of a number of inconveniences I’ve experienced over the past several months, and only today did I finally land on this bug.
The workaround isn’t too fun or easy either. I’m using Python to call
docker exec
in a subprocess, and what I settled on amounts to greppingdocker exec ps ...
to get the PID of the command I just ran, followed bydocker exec kill ...
to kill the process running inside the container. There were also some tricky aspects to what I had to do, but I won’t describe them here.I think this issue should be prioritized more highly because it’s the kind of behavior one takes for granted, and in certain use cases (like in my case) it’s easy not to notice this bug was happening all along.
This issue is still very much existing and causing unexpected and unwanted behavior.
I had that issue with both
docker run
anddocker exec
not dispatching signals to the daemon/container. The root cause is when using--tty
signal proxying is entirely disabled with no way to enable it (even with--sig-proxy
). It affects at leastdocker run
anddocker exec
that share the same code path.Previously
--sig-proxy
was an option to force proxying signals when not using a tty, and hence when using--tty
the proxy got forwarded. Passing both--sig-proxy
and-tty
was leading to an error. That looked like:--tty
--sig-proxy
--tty --sig-proxy
October 2013 patch e0b59ab52b87b8fc15dd5534c3231fdd74843f9f was made to “_Enable sig-proxy by default in run and attach _”. It changed
--sig-proxy
to default to true and made--tty
to always disable signal proxy.--tty
--sig-proxy
--tty --sig-proxy
So what happened with e0b59ab52b87b8fc15dd5534c3231fdd74843f9f is that signal proxying is now enabled by default for non-tty. BUT the patch has a fault: setting
--tty
always disable signal proxying.I am pretty sure that signal-proxying should be enabled by default whether it is a tty or non-tty mode, it is still possible to disable it with
--sig-proxy=false
. A patch would thus have to implement the following changes:--tty
--sig-proxy
--sig-proxy=false
--tty --sig-proxy
--tty --sig-proxy=false
TLDR:
--tty
should not arbitrarily forcesigProxy = false
caused by e0b59ab52b87b8fc15dd5534c3231fdd74843f9fReference: https://phabricator.wikimedia.org/T176747#3749436
Greetings from the year 2022, where I lost my Friday night to this issue. I was also in the situation where I was trying to run
docker exec
commands from within a pythonsubprocess.Popen
call. My most elegant workaround was to find the PID of the persistent process inside the docker container by usingsubprocess.run
to execute:with that PID, I’m able to easily kill it with another
subprocess.run
of:Hello. I’ve run into this issue too. I offer here a workaround done to the best of my limited understanding of how docker works and its internals (most learned while creating this workaround).
First, let me explain the use case: I run a docker image which runs a basic piece of software (a driver, long-time running process, using a number of random ports). Over time, I need to run further commands to interact with this driver, these commands are also long-time running processes. They interact with the driver and in doing so they need to get some resources and free them properly afterwards, which implies, they need to be killed cleanly, i.e. when getting SIGTERM or SIGINT they must do cleanup before exiting. All this software is automatically run by a tty-less environment (supervisord). Summary: I do
docker run -t FLAGS --name DRIVER_CONTAINER MYIMAGE MYDRIVER
and later on every X timedocker exec -t DRIVER_CONTAINER MYDRIVERCLIENT
. I need theexec
commands to exit cleanly and not remain as zombies.Now, the fun part, my workaround: I made a wrapper, using the Docker API and some hacky bits, for
docker exec
to enable signal forwarding. It is contained in this gist which has the class DockerExecWithSignalForwarding. It contains a command line interface that imitatesdocker exec
, supporting (almost) the same flags and nature of use. I install it asdockerexec
to make it look similar todocker exec
. It supports remote DOCKER_HOST via SSH.I hope this may help by: giving an option to people falling into the same issue, and maybe providing an idea on how to do it officially (if there is no better way). And I’d also request feedback on how to improve it (in the comments of the gist probably).
I reproduce it here as it is right now for ease of reading:
The following bash snippet can be used as a workaround for this issue. I basically intercept the SIGTERM to docker exec and do a manual cleanup. It is based on this: http://veithen.github.io/2014/11/16/sigterm-propagation.html
@vishh do you think adding support for
POST /exec/:name/stop
(and maybePOST /exec/:name/kill
) make senses here ( similar toPOST /containers/:name/stop
andPOST /containers/:name/kill
) ? That would actually solve majority of my usecase as I mainly consume the remote API ( which makes the exec process’s unique id available withPOST /exec/:name/create
)It’s probably much harder to do it from the docker cli though as we don’t really expose the exec’s id anywhere.
+1
@th3mis no one is saying this is an issue with docker run. It’s an issue with docker exec and your example still doesn’t work. Signals are not forwarded when you kill the docker exec process no matter what combination of commands you pass to it.
+1
Any updates? We still want this.
mmm, ok, so I agree - I too would expect that
docker exec
would trap the kill signal and pass it on to the Docker daemon, which should then pass the signal on to theexec
’d childI don’t see much in the way of support for this in the API, http://docs.docker.com/reference/api/docker_remote_api_v1.15/#exec-create, so
bug
?@awesomebytes
We use
-it
and thus your solution did not work for us. (but thanks for the great work).I wrote my own solution: https://github.com/hackerschoice/segfault/blob/main/host/docker-exec-sigproxy.c
The tool intercepts traffic on the /var/run/docker.sock and detects when a ‘docker exec’ happens. It registers all signals and then forwards (proxies) the signal to the process running inside the instance.
Old command:
new command:
I wonder why docker wont add the
--sig-proxy=true
to the ‘docker exec’…Half the Internet is crying about stale processes and are being suggested to use--init
and send down the wrong path…We’re hitting this as well, both on docker 1.12.6 and on 17.0.6.0-ce. We have some automated processes that attach to running containers via
docker exec -it
from an SSH session, interacting with the running processes and gathering output to logs. If the SSH connection is disrupted, thedocker exec
’d process remains running. We end up accumulating these stale processes over time.@SvenDowideit ah, my use case is that the
docker exec
process is killed from outside of the container, not the process started bydocker exec
inside the container. For example, after runningdocker exec
, the tree will look like ( pseudo pids here to illustrate the point ) :Now if i do
kill 1025
, which kill thedocker exec
process, the process tree becomes:I would expect
nsenter-exec
to be killed as well and/or maybe docker should expose a way to programatically stopped the exec-process from outside.The new docker exec doc is there https://docs.docker.com/engine/api/v1.43/#tag/Exec/operation/ExecStart
There is still no way to kill a started exec
I ran into the same problem (with hundreds of stale shells not getting SIGHUP when the
docker exec
client received the SIGHUP). Also, looks like half of the Internet thinks that--init
would solve it - obviously not and sends people into the wrong direction.I wrote it down here: https://gist.github.com/SkyperTHC/cb4ebb633890ac36ad86e80c6c7a9bb2
The workaround at the moment is a clean-up cron job - it’s a mess.
Spent several hours running around in circles yesterday, thanks to this “feature”. (Well with kubectl, but I blame docker for starting this mess).
If it’s not going to be fixed, can we at least have a clear warning in the documentation / --help output / man page?
@th3mis ok, I meant running your command via
docker run --init --rm -it --name ubuntu ubuntu:16.04 bash -c 'sleep 77'
instead.If you still want to use docker-exec you have to run your command via the init-process manually:
docker exec ubuntu bash -c '/dev/init -s -- sleep 77'
Otherwise the signals are still not forward to your bash process
docker run
has a flag--sig-proxy
, which is enabled by default when attached.Not sure about changing defaults, but it would be nice to have
docker exec
be able to proxy signals to the process it’s attached to.Good point. We should expose exec jobs belonging to a container.
On Wed, Nov 12, 2014 at 9:59 AM, Sebastiaan van Stijn < notifications@github.com> wrote: