You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Running MCP tools from Docker doesn't properly terminate the container #547
Describe the bug
When running MCP tools from Docker, the close doesn't properly terminate the container. It keeps running in the background.
The tools are working correctly. However, because they have to run using -i it keeps running the container.
The main problem is that when the StdioClientTransport .close() is called, it executes this._abortController.abort(), but doesn't terminate the container for some reason. So when my application finishes, it never exits, because the child process is still running.
To Reproduce
Steps to reproduce the behavior:
Create an MCP client and configure a Docker MCP server:
Expected behavior
It should terminate all child processes started by StdioClientTransport. If the process doesn't terminate properly, it should be killed.
Logs
No relevant logs.
Additional context
I am running it on Mac OS Sequoia using the latest version of Docker and the latest version of the library 1.12.0.
+1, This is a crucial issue, which if not fixed would cause your local setup to be overcrowded with orphaned Docker Containers that should have been stopped. This is especially the case if you are using dockerized MCP servers across multiple projects where each project is using an AI coding agent. Currently the only workaround at the MCP server level is to fork their repository and implement proper process shutdown behaviour yourself, build and then run the docker container, which is not the most scalable solution if you rely on many MCP servers for different things.
Alternatively, I was able to work around this by passing the --init flag to the docker run command.
Summary
The --init flag for docker run tells Docker to inject a minimal init process (based on Tini) as PID 1 inside the container, which forwards signals (e.g., SIGTERM, SIGINT) to your application and reaps zombie child processes automatically, ensuring clean shutdowns and preventing process table leaks without requiring any changes to your Docker images. oai_citation:0‡docs.docker.comoai_citation:1‡baeldung.com
What Is the --init Flag?
When you add --init to docker run, Docker launches its built-in init binary (docker-init, Tini-based) as the first process (PID 1) inside the container before your specified command. oai_citation:2‡docs.docker.com
How It Works Internally
Init Injection
Docker locates the docker-init executable bundled with the daemon (often /usr/bin/docker-init) and starts it as PID 1, then execs your application process. oai_citation:3‡stackoverflow.com
Signal Forwarding
The init process proxies signals (SIGTERM, SIGINT, etc.) from the Docker daemon to all descendant processes, allowing each to handle shutdown gracefully. oai_citation:4‡docs.docker.com
Zombie Reaping
As PID 1, the init process performs wait() calls on exited child processes, preventing zombie accumulation in the container. oai_citation:5‡docs.docker.com
Benefits of Using --init
Clean Process Management: Prevents zombies that could otherwise exhaust the container’s process table over time. oai_citation:6‡docs.docker.com
Graceful Shutdown: Ensures all child processes receive termination signals properly, reducing the risk of hangs or data corruption. oai_citation:7‡stackoverflow.com
Zero Image Changes: No need to bake an init into your Dockerfile—just add a flag to your docker run invocation. oai_citation:8‡baeldung.com
Usage Examples
# Run an image with the built-in init for PID 1 semantics
docker run --init my-image
Reacted by Gaurav Priyolkar, John Ritsema, Matvii Hodovaniuk, Laszlo Laszlo, raffael-gr, toan-trieu-ts, keyesdav and Firas
Activity
modelcontextprotocol#547 kill the child process if it's not properly …
dgouvea commentedon May 26, 2025
I proposed a fix for this problem here, and I am open to any changes you suggest.
rishitank commentedon Jun 16, 2025
+1, This is a crucial issue, which if not fixed would cause your local setup to be overcrowded with orphaned Docker Containers that should have been stopped. This is especially the case if you are using dockerized MCP servers across multiple projects where each project is using an AI coding agent. Currently the only workaround at the MCP server level is to fork their repository and implement proper process shutdown behaviour yourself, build and then run the docker container, which is not the most scalable solution if you rely on many MCP servers for different things.
rishitank commentedon Jun 18, 2025
Alternatively, I was able to work around this by passing the
--initflag to thedocker runcommand.Summary
The
--initflag fordocker runtells Docker to inject a minimal init process (based on Tini) as PID 1 inside the container, which forwards signals (e.g., SIGTERM, SIGINT) to your application and reaps zombie child processes automatically, ensuring clean shutdowns and preventing process table leaks without requiring any changes to your Docker images. oai_citation:0‡docs.docker.com oai_citation:1‡baeldung.comWhat Is the
--initFlag?--inittodocker run, Docker launches its built-in init binary (docker-init, Tini-based) as the first process (PID 1) inside the container before your specified command. oai_citation:2‡docs.docker.comHow It Works Internally
Docker locates the
docker-initexecutable bundled with the daemon (often/usr/bin/docker-init) and starts it as PID 1, thenexecs your application process. oai_citation:3‡stackoverflow.comThe init process proxies signals (SIGTERM, SIGINT, etc.) from the Docker daemon to all descendant processes, allowing each to handle shutdown gracefully. oai_citation:4‡docs.docker.com
As PID 1, the init process performs
wait()calls on exited child processes, preventing zombie accumulation in the container. oai_citation:5‡docs.docker.comBenefits of Using
--initdocker runinvocation. oai_citation:8‡baeldung.comUsage Examples
# Run an image with the built-in init for PID 1 semantics docker run --init my-imagesanguino commentedon Sep 6, 2025
Hi,
@rishitank It works!!! Thank you so much, I was going crazy
felixweinberger commentedon Nov 3, 2025
Closing as this seems resolved by the response from @rishitank, thank you!