In this article
When docker stop waits until forced termination, inspect the process tree and PID 1. A shell wrapper may fail to forward signals to its worker, or the main process may not handle TERM. A separate issue arises when nobody reaps children that have already exited.
When docker stop waits until forced termination, inspect the process tree and PID 1. A shell wrapper may fail to forward signals to its worker, or the main process may not handle TERM. A separate issue arises when nobody reaps children that have already exited.
Reconstruct the launch command
Preserve the image ENTRYPOINT, CMD and effective arguments. Establish which program became PID 1 inside the container and which process parents the worker. An interactive shell can create a different tree from the production entrypoint. In a shell script that starts one main application, exec replaces the shell instead of creating another child. Correct shutdown still depends on the application’s signal handling, not merely the Dockerfile form.
Separate signaling from cleanup
Docker directs the stop signal to the main process. Linux gives PID 1 special signal behavior, so the program must implement the required response. Forwarding TERM to a child and reaping exited children are separate responsibilities. —init adds a small init process for relevant lifecycle functions, but cannot invent application-specific persistence or cleanup. Its presence does not automatically establish that every worker received the signal and released its resources.
Test a wrapper scenario
In an illustrative case, a script starts a background worker and waits. Following stop, the log records shell termination but the worker never writes its final marker. Compare this with a correct exec arrangement or explicit trap and forwarding appropriate to the actual tree. Then create a separate short-lived child and check whether it leaves the zombie state. The test does not require loading a real model or changing CUDA settings.
| Test evidence | Property being checked |
|---|---|
| PID/PPID tree | The stop-signal recipient is identified |
| Worker TERM marker | Signal handling is confirmed |
| Shutdown duration | Waiting before forced termination is visible |
| Exited child state | Reaping responsibility is verified |
Correct the smallest relevant layer
For a single main application, avoid an unnecessary shell layer. For multiple processes, explicitly define supervision and shutdown order. Keep a bounded waiting interval that accommodates the intended cleanup. Increasing the stop timeout merely hides missing forwarding when the worker never receives a signal. Verify permission to write final state too: correctly delivered TERM is insufficient if the handler blocks or writes to an inaccessible path.
Exercise several shutdown states
Repeat startup and stop while idle, under work and after a child process fails. Preserve expected exit codes and final markers without customer data. The resulting artifact should contain the process tree, signal path, reaping owner and maximum shutdown allowance. These details also matter when deploying through Kubernetes, whose grace period bounds termination. Disappearance of the container object should not be the only evidence that cleanup inside the application actually completed. Check process behavior directly before treating a successful control-plane operation as a successful application shutdown.
Related operational reading: gpu containers vs vms; vllm docker first launch.