Suggest an editImprove this articleRefine the answer for “docker exec vs docker attach: what is the difference?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`docker exec`** spawns a NEW process inside a running container. **`docker attach`** connects to PID 1's stdio. Killing the exec process leaves the container running; killing the attached PID 1 stops the container. ```bash docker exec -it web sh # new shell, separate process — exit safely docker attach web # connect to nginx's stdio — Ctrl+C stops nginx ``` **Key:** `exec` is what you almost always want for debugging or inspection. `attach` is for cases where you need to interact with PID 1 itself — a REPL as PID 1, console-based apps. Detach from attach with Ctrl+P, Ctrl+Q (does NOT kill the container).Shown above the full answer for quick recall.Answer (EN)Image**`docker exec` and `docker attach`** are both ways to interact with a running container, but they connect to different things. Misunderstanding which is which leads to a class of bugs where you accidentally kill production by pressing Ctrl+C in the wrong window. ## Theory ### TL;DR - `docker exec` = **new process** inside the container. The container's existing PID 1 keeps running independently. - `docker attach` = **connect to PID 1's stdio**. You see what PID 1 sees (its stdin/stdout/stderr). - Killing your `exec` shell: only your shell exits. Container stays running. - Killing/Ctrl+C your `attach` session: PID 1 receives SIGINT. **The container probably stops.** - **Detach from attach without killing:** Ctrl+P then Ctrl+Q (must be `-it` mode). - 99% of the time you want `exec`. `attach` is rare. ### What `docker exec` does ```bash $ docker run -d --name web nginx $ docker exec -it web sh / # ps aux USER PID COMMAND root 1 nginx: master process nginx 29 nginx: worker process root 45 sh # ← my shell, separate process root 51 ps aux / # exit # Container still running. ``` The shell is process 45 inside the container. It runs alongside nginx (PIDs 1 and 29). Exit the shell → process 45 ends, nginx untouched, container still running. ### What `docker attach` does ```bash $ docker run -d --name web nginx $ docker attach web # (silent — nginx's stdio, with no current output) # Press Ctrl+C # nginx receives SIGINT → exits → container stops ``` You are connected to nginx's stdio. Anything nginx prints, you see. Anything you type, nginx receives on stdin. Ctrl+C sends SIGINT to nginx. nginx exits. Container ends. **For debugging, this is almost never what you want.** ### Side-by-side | | `docker exec` | `docker attach` | |---|---|---| | Creates a process | yes (new) | no (connects to PID 1) | | Kills container on Ctrl+C | no | **yes** (sends SIGINT to PID 1) | | Ctrl+P, Ctrl+Q to detach safely | n/a | yes | | Use for | debugging, inspection, ad-hoc commands | REPLs as PID 1, console apps | | Common mistake | none really | accidentally killing prod | ### Detaching from attach The escape sequence to leave `attach` without killing PID 1: ``` Ctrl+P, Ctrl+Q ``` Must be in `-it` mode (interactive + TTY). Without `-t`, there is no terminal sequence to interpret; without `-i`, stdin is closed. Without escape sequence, your only options are Ctrl+C (kills container) or kill the docker process from outside. In shells that override Ctrl+P (some `tmux` configs), you may need to remap before attaching. ### When `attach` is actually useful #### REPLs as PID 1 ```bash docker run -d --name nodejs node:22 node # nodejs running as PID 1, REPL waiting for input docker attach nodejs > 1+1 2 > .exit # Ctrl+P, Ctrl+Q to detach instead ``` A Python or Node REPL run as PID 1 only takes input via attach. exec would spawn a new shell, which is not what you want. #### Console-based apps Apps that interact via stdio as their primary interface (chess servers, console games, certain admin tools) need attach. #### Watching live PID 1 output ```bash docker attach web # nginx access log streams in real time ``` Though `docker logs -f web` is usually a better choice — same effect, no risk of killing. ### Common mistakes **Using attach when you wanted exec** ```bash # WRONG docker attach web # connects to nginx's stdio # Press Ctrl+C → kills nginx → container stops → outage # RIGHT docker exec -it web sh # new shell # Press Ctrl+D (or exit) → shell ends → container untouched ``` The most common attach mistake is treating it like exec. Same intuition ("connect to running container"), very different consequences. **Forgetting `-it` with attach** ```bash docker attach --no-stdin web # disables stdin # can no longer Ctrl+P, Ctrl+Q to detach (no TTY) # only Ctrl+C, which kills ``` If you must attach without TTY, accept that Ctrl+C is your only exit. Better: just don't. **Using `--sig-proxy=false` in attach without understanding** ```bash docker attach --sig-proxy=false web # Ctrl+C now does NOT propagate to PID 1 — container survives ``` A workaround for safer attach. But if you need this, you probably wanted `exec` anyway. **Trying to attach to a stopped container** ```bash $ docker attach stopped-web Error: container is not running ``` Attach requires running. Use `docker start -ai stopped-web` to revive an exited container with stdio attached (different but related). ### Real-world usage - **`exec`** for 99% of debugging: shell into a running container, run a one-off command, inspect files, check env. Safe and standard. - **`attach`** specifically for: interacting with REPLs as PID 1 (rare), console apps where stdio is the API (rare), watching live output without `docker logs` (rare; logs are usually better). - **Never `attach`** to a production web server you do not want killed. Use `docker logs -f` instead. ### Follow-up questions **Q:** Why does Ctrl+C kill the container with attach but not with exec? **A:** With attach, you are connected to PID 1's stdio. Ctrl+C sends SIGINT to PID 1 (the main process). PID 1 exits, container exits. With exec, your shell is a separate process; Ctrl+C kills the shell, not PID 1. **Q:** Can multiple users attach to the same container? **A:** Yes — they all see PID 1's output and share stdin. Acts like a screen session. Useful for collaborative debugging; risky because anyone could Ctrl+C accidentally. **Q:** What is the difference between `docker attach` and `docker exec -it container bash`? **A:** Attach connects to existing PID 1's stdio. Exec creates a new bash process inside the container. The new bash is independent; PID 1 is shared. **Q:** What does `docker run -d` then `docker attach` give me vs `docker run` (no -d)? **A:** Same outcome (you see PID 1's output). The `-d` + `attach` combo is useful when you want to start detached, do other things, then attach later. `docker run` without `-d` is attach-by-default. **Q:** (Senior) When would you write a custom container that requires `docker attach` over `docker exec`? **A:** When the container's purpose IS to interact via stdio as the primary interface — like a custom REPL, an interactive admin tool that the user runs occasionally rather than as a daemon, or a game server with admin console. Even then, modern designs prefer HTTP or gRPC APIs over stdio attachment for usability and multi-user support. Pure-stdio interfaces are increasingly rare; if you find yourself reaching for attach, ask whether your design might be a relic. ## Examples ### Safe debugging with exec ```bash # Production web server. Investigate WITHOUT risking outage. docker exec -it web sh / # cat /etc/nginx/nginx.conf / # netstat -tlnp / # ps aux / # exit # nginx never noticed; uptime preserved. ``` ### Risky live tail with attach ```bash # DO NOT do this in production docker attach prod-web # Streams live access logs. # Accidental Ctrl+C → SIGINT → nginx exits → 502 for users. # Better: docker logs -f prod-web # same output, safe ``` ### Detach demo ```bash $ docker run -d --name pyrepl python:3.13 python # Python REPL waiting in background as PID 1 $ docker attach pyrepl >>> 2 + 2 4 >>> # Now press Ctrl+P, then Ctrl+Q read escape sequence $ docker ps --filter name=pyrepl STATUS NAMES Up 2 minutes pyrepl # still running ``` Detach safely; container keeps the REPL alive; you can re-attach later. ### When attach is actually needed ```bash # Custom container designed as an interactive tool docker run -d --name console myorg/admin-console:1.0 docker attach console admin> help admin> reset --user 42 admin> exit # Custom 'exit' command tells the app to shut down. ``` If the app's design is "talk to me via stdio", attach is the only way. But this design is uncommon.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.