Typing exit in a Docker container stops it sometimes and leaves it running other times. The deciding factor is PID 1, the container’s main process. When that process ends, the container ends with it.
People get out through an interactive shell, docker exec, or docker attach, and each one behaves differently. Docker Docs (2026) documents an Alpine container started without -i and -t, where Ctrl+P then Ctrl+Q did nothing and Ctrl+C ended the container with status Exited (130).
Start that same container with -i and -t and Ctrl+P then Ctrl+Q detaches the terminal. The container stays Up.
What does it mean to exit a docker container?
Exiting only ends your terminal session. Whether the container stops too depends on what kind of session it was, because Docker treats a container as a single process on the host and stops it when that process ends.
Docker Docs (2026) describes each container as a process with its own file system and networking, plus an isolated process tree. If you want the background, there’s a plain-language breakdown of how Docker containers work.
Stopped or still running
A stopped container has lost its main process, and docker ps -a lists it with an Exited status. A container that’s still running only lost your session (it ended or detached), so docker ps lists it as Up.
Docker Engine records the state, and the Docker CLI reads it back with docker ps.
At the prompt both outcomes look the same. You need docker ps to tell them apart.
Exit is not stop
Your terminal connection is the session. The container is the PID 1 process, and it keeps going until it finishes by itself or gets a stop signal.
The docker stop command works from outside the session. It sends SIGTERM to the main process, then SIGKILL after a grace period (Docker Docs, 2026).
So the outcome depends on PID 1, not on which key you press.
What decides whether the container stops when you exit?
PID 1 decides. The container stops the moment that process ends, which is why exit stops a container started with docker run -it ubuntu bash (bash is PID 1 there).
How PID 1 gets chosen
Each Docker image carries default ENTRYPOINT and CMD instructions, and arguments after the image name in docker run replace CMD.
Run ubuntu with bash and exit ends bash, so the container shows Exited. Alpine with sh gives the same result, since Alpine Linux ships sh instead of bash. Nginx is different. Its web server never ends on its own, so that container keeps running.
Whichever process starts first becomes PID 1, and its lifetime is the container’s lifetime.
Why a container exits immediately
Docker Docs (2026) explains that the -i flag keeps STDIN attached, which stops an sh main process from exiting right after start.
A command that finishes, like echo, takes PID 1 down with it and the status becomes Exited. A long-running server keeps PID 1 alive, so the status stays Up. An interactive shell with -i and -t lasts until you type exit.
A container with no foreground process exits immediately. Run docker ps -a to see stopped containers, since docker ps alone lists only running ones.
Docker Docs (2026) names docker start as the way to restart a stopped container with its changes intact.
How do docker run, docker exec, and docker attach behave on exit?
With docker run -it the shell is PID 1, so exit stops the container. docker exec -it opens a second process instead, and exit leaves the container alone. docker attach is the odd one because it plugs into the PID 1 streams, so anything you send lands on PID 1 itself.
| Session type | PID 1 involved | Effect of exit | Effect of Ctrl+C |
|---|---|---|---|
| docker run -it | Yes, the shell is PID 1 | Container stops | Interrupts the running command, shell stays |
| docker exec -it | No, a second process | Container keeps running | Interrupts that command only |
| docker attach | Yes, shares the PID 1 streams | Container stops if PID 1 is the shell | Signals PID 1 |
docker run -it and PID 1
The command docker run -it ubuntu bash starts bash as PID 1 with a pseudo-TTY. Type exit and bash ends, and the container stops with it.
The GNU Bash Reference Manual (Edition 5.3, 2025) states that exit without a number returns the status of the last command executed, so a clean session ends with exit code 0.
The -i flag keeps STDIN open even when nothing is attached, and -t allocates a pseudo-TTY.
docker exec as a side session
Run docker exec -it mycontainer sh and you get a new shell next to PID 1. Exit that shell and PID 1 keeps running.
Docker Docs (2026) states that an exec command runs only while PID 1 runs and does not restart with the container. A paused container rejects docker exec with an error and exit code 1.
docker attach and shared streams
Docker Docs (2026) shows an Alpine container running top -b without -i or -t. Ctrl+P Ctrl+Q had no effect, and Ctrl+C ended the container with status Exited (130).
The same page says Ctrl+C sends SIGKILL, then says it sends SIGINT when –sig-proxy is true, the default. Exit code 130 equals 128 plus the SIGINT number 2 (GNU Bash Reference Manual, 2025; Linux man-pages, 2026), so the SIGINT statement describes the default.
To stop the CLI from proxying signals to the process, set –sig-proxy=false. If you’d rather detach with Ctrl+P Ctrl+Q, start the container with -i and -t.
Which exit method fits which situation?
Use exit or Ctrl+D when the shell is yours to end. Ctrl+P then Ctrl+Q leaves the container running. For a clean shutdown, run docker stop from a second terminal. And for inspection sessions, docker exec means exit never touches the service.
exit and Ctrl+D
exit is a shell builtin in bash and sh, and Ctrl+D sends end-of-file at an empty prompt. Both end the shell.
Both work in every image that ships a shell, and both return a clean exit code when the last command succeeded. The downside is that the container stops when the shell is PID 1. Ctrl+D also fails to exit while text sits on the prompt line.
Ctrl+P then Ctrl+Q
This combination detaches your terminal and leaves PID 1 running. It requires a container started with -i and -t.
| Pros | Cons |
|---|---|
| Container keeps running | Does nothing without -i and -t |
| Reattach later with docker attach | Conflicts with other applications that use the same keys (Docker Docs, 2026) |
Ctrl+C
Ctrl+C sends SIGINT, and what happens next depends on the session type. In docker run -it or docker exec -it it interrupts a runaway command without ending the shell. In docker attach it signals PID 1, so the container ends if PID 1 exits on SIGINT.
docker stop from a second terminal
This ends the container cleanly, with SIGTERM first and SIGKILL after the grace period. The catch is that the container is gone afterward, so nothing stays running for you to reattach to.
The safer default for inspection
I’d reach for docker exec -it CONTAINER sh for inspection. The new shell is a second process, so exit never touches PID 1.
It’s fine for reading config files or listing processes. Outbound network tests work too.
A quick Docker command cheat sheet keeps the flag names within reach.
How do you exit a docker container without stopping it?

Press Ctrl+P then Ctrl+Q, the default detach sequence. The Docker CLI handles it, and it works only when the container started with both -i and -t.
- Start the container with docker run -dit –name topdemo2 alpine /usr/bin/top -b.
- Attach with docker attach topdemo2, then press Ctrl+P and Ctrl+Q. The CLI prints read escape sequence.
- Verify with docker ps -a –filter name=topdemo2. The status reads Up.
- Reattach any time with docker attach topdemo2.
When the detach sequence does nothing
Docker Docs (2026) states that a container started without -i and -t forwards signals to the attached process, so the default Ctrl+P Ctrl+Q sequence produces no effect.
The same thing happens when the container was started with -d only, or with docker run and no -it, or when the detach keys were changed in config.json (more on that below).
Reattaching by name or ID
Docker Docs (2026) lets you identify a container by name, short ID, or long ID. So docker attach topdemo2 works, and so does docker attach fde88b83c2c2.
docker attach shows the output of the ENTRYPOINT and CMD process. The screen looks frozen when that process has nothing to print (Docker Docs, 2026).
How do you change the detach keys?
Pass –detach-keys to docker run, docker exec, docker attach, or docker start to change the sequence for one container. Set the detachKeys property in ~/.docker/config.json to change the default for every container your Docker CLI starts.
Docker Docs (2026) calls a custom sequence useful when the default conflicts with keys used by other applications.
Per-container override with –detach-keys
The flag takes one sequence, either a letter from a to Z or ctrl- combined with one allowed character (Docker Docs, 2026). The allowed characters are listed here.
- a to z, a single lowercase letter
- @ (at sign)
- [ (left bracket)
- \\ (two backward slashes)
- \_ (underscore)
- ^ (caret)
Valid examples include a, ctrl-a, X, and ctrl-\\. A full command reads docker attach –detach-keys=”ctrl-x” topdemo2.
Global default in config.json
| Method | Scope | Overrides |
|---|---|---|
| –detach-keys flag | One container or session | config.json and the default |
| detachKeys in config.json | Every container started by your Docker CLI | The default Ctrl+P Ctrl+Q |
| No setting | Every container | Nothing |
The Docker Docs (2026) sample sets detachKeys to ctrl-e,e. The value is a comma-separated list, so the two presses run in order.
Without a credential store, docker login writes registry credentials into config.json (Docker Docs, 2026). Keep the file out of version control.
What do docker exit codes mean?
Zero means success. 125 points at the Docker daemon itself, 126 means the command can’t be invoked, and 127 means it wasn’t found. Anything else is the container command’s own exit code, which is how you end up with 130, 137, and 143 for SIGINT, SIGKILL, and SIGTERM.
Errors before the command runs
A 125 means the error is in the Docker daemon itself, such as an unknown flag. A 126 means the container command cannot be invoked, and 127 means it was not found. Every other code is the exit code of the container command itself (Docker Docs, 2026).
Zero means success, and any non-zero code means failure (GNU Bash Reference Manual, 2025).
Docker Docs (2026) shows docker attach returning 13 to the caller after exit 13 inside an Alpine shell, and docker ps -a then listing Exited (13).
Signal-based exits
| Code | Signal | Number | Typical cause |
|---|---|---|---|
| 130 | SIGINT | 2 | Ctrl+C reaches the process |
| 137 | SIGKILL | 9 | docker kill, or the end of the docker stop grace period |
| 143 | SIGTERM | 15 | SIGTERM ends the process |
Bash reports a process killed by signal N as 128 plus N (GNU Bash Reference Manual, 2025), and Linux numbers SIGINT 2, SIGKILL 9, and SIGTERM 15 on x86 and ARM (Linux man-pages, 2026). Combining both sources gives 130, 137, and 143 without a lookup table.
SIGKILL cannot be caught, blocked, or ignored (Linux man-pages, 2026), so 137 marks a forced end.
docker stop waits 10 seconds by default for Linux containers before it sends SIGKILL (Docker Docs, 2026).
Reading the code after exit
docker ps -a shows Exited in the STATUS column with the code in parentheses. docker inspect stores ExitCode in its State section. docker wait blocks until the container stops and then prints the code, and docker logs shows the output that led to it.
Read the code first, then the logs. The number names the cause, and the logs confirm it.
How do you stop a docker container from another terminal?
Find the name with docker ps, then run docker stop NAME. That gives the process time to clean up. docker kill NAME gives it none and ends things immediately.
| Command | Signal sent | Forces an exit | Best for |
|---|---|---|---|
| docker stop | Image stop signal, SIGTERM if none is set | Yes, after the timeout | Clean shutdown |
| docker stop -t -1 | Same as docker stop | No, waits indefinitely | Slow shutdown work |
| docker kill | SIGKILL by default | Not applicable | Hung process |
docker stop and its timeout
The -t flag sets how long docker stop waits before forcing an exit. Setting -t to -1 removes the limit, and the daemon waits indefinitely (Docker Docs, 2026).
You can set a default per container with –stop-timeout on docker run or docker create, then override it for a single command with -t on docker stop.
A separate step-by-step guide to stopping a Docker container covers the same command for beginners.
Changing the stop signal
The signal can be baked into the image with STOPSIGNAL in the Dockerfile. –stop-signal on docker run or docker create sets it per container, and -s on docker stop sets it for one command.
Signals go in by name, such as SIGINT, or by number. SIGTERM applies only when no signal is configured (Docker Docs, 2026).
docker kill for a hung process
docker kill sends SIGKILL to the main process by default (Docker Docs, 2026). Reach for it when docker stop cannot end a stuck container.
The –signal flag changes the signal, and a non-terminal signal leaves the container running. Docker Docs (2026) cites SIGHUP, signal number 1, as usually non-terminal.
- docker kill –signal=SIGHUP my\_container
- docker kill –signal=HUP my\_container
- docker kill –signal=1 my\_container
All 3 commands are equivalent, because the SIG prefix is optional.
Why does a docker container ignore Ctrl+C?
PID 1 in a Linux container ignores any signal that has only its default action, so an application running as PID 1 without a SIGINT handler drops Ctrl+C. The container keeps running until docker stop or docker kill ends it.
PID 1 and default signal actions
Docker Docs (2026) states that Linux treats PID 1 specially, so the process does not terminate on SIGINT or SIGTERM unless its code handles them.
An ordinary process with no SIGINT handler ends when it receives one. A PID 1 process drops the same signal.
A program that installs its own handler, such as top -b in the documented attach example, still exits on Ctrl+C.
Shell form hides the executable
In shell form, ENTRYPOINT command param1 runs under /bin/sh -c, which does not pass signals. Exec form, ENTRYPOINT [“executable”, “param1”], starts the executable directly as PID 1.
Docker Docs (2026) states that a shell-form executable is not the container’s PID 1 and receives no Unix signals. docker stop reaches the shell and never the application.
Fixing signal handling
- Rewrite ENTRYPOINT and CMD in exec form so the application is PID 1.
- Add –init to docker run. Docker Docs (2026) describes it as an init inside the container that forwards signals and reaps processes.
- Rerun with -it and press Ctrl+C. The container exits, and docker ps -a shows the status.
The –init flag runs tini, a small init program that forwards SIGINT and SIGTERM to the application (Tini project README).
Should you remove the container after exit?
Use –rm for throwaway sessions and keep the container when you need its logs or filesystem. –rm removes the container and its anonymous volumes on exit, while a container without it stays as Exited until you remove it.
–rm for throwaway sessions
docker run –rm -it alpine sh leaves nothing behind after exit, and no stopped entries pile up in docker ps -a. Anonymous volumes are deleted together with the container (Docker Docs, 2026).
Named volumes and bind mounts survive, because data written to a volume persists after the container is removed (Docker Docs, 2026).
Keeping an exited container
| Choice | Choose when | Trade-off |
|---|---|---|
| Keep the container | You need logs or the writable layer | Exited entries pile up in docker ps -a |
| Use –rm | The session is disposable | Logs vanish with the container |
| Set a restart policy | The service must return after exit | After a manual stop, the policy is ignored until the daemon restarts or you start the container again |
docker start brings an exited container back with all its previous changes intact (Docker Docs, 2026). Add -a and -i to attach your terminal again.
Cleaning up exited containers
docker rm removes one stopped container by name or ID. docker container prune removes every stopped container after a confirmation prompt, and -f skips that prompt. Add –filter until=5m to remove only containers created more than 5 minutes ago (Docker Docs, 2026).
Restart policies
| Policy | Restarts after exit | After a manual stop | After a daemon restart |
|---|---|---|---|
| no | Never | Stays stopped | Stays stopped |
| on-failure | Only on a non-zero exit code | Ignored until a manual restart | Not restarted |
| always | Every exit | Ignored until the daemon restarts | Restarted |
| unless-stopped | Every exit | Stays stopped | Restarted, unless it was stopped manually |
A policy takes effect only after the container has been up for at least 10 seconds (Docker Docs, 2026).
The manual route is covered in a guide on how to restart a Docker container after it exits.
When do these exit methods not apply?
A container started without -it ignores detach keys. An attached Compose stack treats Ctrl+C as a stop for every service. A restart policy can revive a container you just exited, and stopped containers reject attach and exec.
| Situation | Method | Result |
|---|---|---|
| Container without -i and -t | Ctrl+P then Ctrl+Q | No detach |
| Attached Compose stack | Ctrl+C | Every service stops |
| Restart policy always | exit | Container comes back |
| Stopped container | docker attach or docker exec | Command rejected |
Attached Compose stacks
Docker Docs (2026) states that docker compose up attaches to every service and stops all containers when the command exits. Interrupting it with SIGINT (Ctrl+C) or SIGTERM stops the containers and returns exit code 0.
Read up on Docker Compose projects before you run a multi-service stack in the foreground.
docker compose up –detach leaves the stack running in the background. –abort-on-container-exit stops every container when any one stops, and docker compose down stops and removes the stack.
Restart policies keep the container alive
In a foreground run, stopping the container ends the attached CLI, whatever the policy says (Docker Docs, 2026).
The documented case is a script that counts to five and exits with an error, run with –restart always. The CLI ended while docker ps still showed the container running or restarting.
docker attach reconnects your terminal between restarts, and the CLI detaches again on the next exit.
Stopped containers reject attach and exec
docker exec runs a command in a running container, and docker attach connects to a running one (Docker Docs, 2026). A stopped container needs docker start first.
docker start -ai CONTAINER restarts it and attaches your terminal. Once the container is Up again, docker exec -it CONTAINER sh works as usual.
FAQ on How To Exit Docker Container
Is there a docker exit command?
No. The Docker CLI has no exit subcommand, because exit is a shell builtin in bash and sh. Inside a container it ends the shell, and it returns the last command’s status when you pass no number.
Does exiting a docker container delete its data?
No. Exit ends the process, and the stopped container keeps its writable layer until you remove it. The –rm flag deletes the container and its anonymous volumes on exit, while named volumes persist (Docker Docs, 2026).
Does exit code 137 always mean out of memory?
No. Exit code 137 means SIGKILL ended the process. The kernel OOM killer, docker kill, and docker stop after its grace period all produce it, so check docker logs and the memory limit before blaming memory.
How do you list exited docker containers?
Run docker ps -a to list every container. Run docker ps -a –filter status=exited to show only stopped ones.
The STATUS column reports Exited with the exit code in parentheses.
How do you exit a docker container on Windows?
The Docker CLI commands docker stop, docker exec, and docker attach work the same way through Docker Desktop. Windows containers differ in one default: docker stop waits 30 seconds before forcing an exit (Docker Docs, 2026).
Where Does How To Exit Docker Container Break Down?
Most failures with how to exit Docker container sessions trace back to a missing TTY that breaks detach keys, a PID 1 without handlers that drops Ctrl+C, and a restart policy that revives the container after exit.
Fix them in cost order, cheapest first, because each later fix changes more of the container’s behavior.
Start every interactive container with -it. Next, switch to exec form or add –init. Last, choose –rm or a restart policy on purpose.
The trade-off sits in the second fix. –init places an init process at PID 1, so the application no longer runs as PID 1.
Docker Docs confirmed this position on 29 September 2026, and a Docker Engine release that changes PID 1 signal handling ends it.
Once the containers are gone, remove unused Docker images to reclaim the disk space they held.
- How to Turn On Dark Mode in Notepad++ (Built-In, No Plugin) - October 3, 2026
- PostgreSQL Cheat Sheet - October 2, 2026
- How to Repair a Corrupt SQL Server Database Without Any Data Loss - October 2, 2026



