Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot docker stop (SIGINT?) a tail -f /dev/null command #4953

Closed
ORESoftware opened this issue Mar 19, 2024 · 3 comments
Closed

cannot docker stop (SIGINT?) a tail -f /dev/null command #4953

ORESoftware opened this issue Mar 19, 2024 · 3 comments

Comments

@ORESoftware
Copy link

Description

I we do this:

docker run -d --name foo --entrypoint tail xyz  -f /dev/null

effectively we are running

tail -f /dev/null

but I cannot run:

docker stop foo

I have to docker kill foo, to get it to exit.

Likewise, I cannot SIGINT it, using ctrl-C
which is always a bad user experience.

I feel like it should be able to trap SIGINT's always. But it might be impossible to always to have the desired shell experience.

Reproduce

same as above

Expected behavior

should always be able to stop a container

docker version

24

docker info

docker 24

Additional Info

No response

@yogesh-aggarwal
Copy link

@ORESoftware Thanks for reporting the issue here but I think you are somewhat mistaken by the syntax you have used for running the docker run command. Let me tell you why:

What you intended to run:

tail -f /dev/null

What you effectively ran:

tail

What?? Yes. As you haven't "quoted" the command you want to run as the entrypoint, the -f /dev/null option is treated as option not for your "entrypoint" but for your "docker run ...". Here's the command you should run:

docker run -d --name foo --entrypoint "tail -f /dev/null" xyz

Note: There's no such flag as -f in the docker run command so it will effectively get ignored.

As for why you are stuck and not able to SIGINT, it looks like some issue with the container you are running itself.

@thaJeztah
Copy link
Member

I think you are somewhat mistaken by the syntax you have used for running the docker run command. Let me tell you why:

No, I think the syntax used is correct; the example uses xyz as image name, so;

docker run -d --name foo --entrypoint tail <image name> -f /dev/null

In the above, the entrypoint is tail, and the "command" (which is used as arguments for the entrypoint) -f /dev/null; doing this with an alpine image;

docker run -d --name foo --entrypoint tail alpine -f /dev/null

docker inspect --format '{{ json .Config.Entrypoint }}' foo
["tail"]

docker inspect --format '{{ json .Config.Cmd }}' foo
["-f","/dev/null"]

However, I'm not able to reproduce the problem reported; the container is ultimately stopped, but it takes ~10 seconds before it completes;

time docker stop foo
foo

real	0m10.164s
user	0m0.006s
sys	0m0.008s

docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS                        PORTS     NAMES
e2133f3661bf   alpine         "tail -f /dev/null"      About a minute ago   Exited (137) 5 seconds ago              foo

So, why does it take 10 seconds?

In this example, tail is the entrypoint (and not running inside a shell) which means that it's running as PID1 inside the container. Some processes act different when running as PID1, and ignore signals (SIGTERM) in that case; this is on purpose as on a Linux machine, PID1 should never be stopped, unless you're restarting the machine. What happens when you run docker stop is that docker sends the process a SIGTERM signal to allow it to shutdown gracefully. In this case, that signal is ignored, so the process / container won't stop. If the container did not shutdown gracefully within 10 seconds, the Docker Daemon will now force it to stop by sending a SIGKILL (this signal cannot be ignored, even by processes running as PID1), and the container will stop.

More information can be found in the docker container kill reference; https://docs.docker.com/reference/cli/docker/container/kill/

There are some options though;

  • you can run tail in a shell (either docker run /bin/sh -c 'tail -f /dev/null or docker run --entrypoint /bin/sh <image> -c 'trail -f /dev/null)
  • you can use the --init option; this inserts a minimal process manager / process reaper into the container (by default that is tini) which will be running as PID1. The tail command will now no longer be running as PID1 (thus handle signals as usual), and the tini init process takes care of reaping processes in the container on shutdown.

Repeating the earlier example, but now with --init shows that the container stops immediately;

docker run -d --name foo --init --entrypoint tail alpine -f /dev/null

time docker stop foo
foo

real	0m0.127s
user	0m0.006s
sys	0m0.006s

docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                        PORTS     NAMES
17b5f5cd080d   alpine         "tail -f /dev/null"      27 seconds ago   Exited (143) 15 seconds ago             foo

@thaJeztah
Copy link
Member

Based on the above, I don't think there's a bug at hand here, so I'll close this ticket, but feel free to continue the conversation.

@thaJeztah thaJeztah closed this as not planned Won't fix, can't repro, duplicate, stale May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants