Safely Attach to a Running Docker Container
You will finish with a reliable way to watch a running container's output, interact with its main process when it has a terminal, and leave it running when you disconnect. This guide uses Docker CE CLI 29.8.1, installed as package docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell, access to the Docker daemon, and the name or ID of a running container. Most Docker commands may need permission to access the daemon, commonly through the docker group or sudo; use the least privilege already approved on your host. Nothing here needs root inside the container.
Safety checkpoint
Attaching connects your terminal to the container's standard input, output and error. A key press can reach the container process. Confirm the container name before you attach, especially on a production host.
1. Confirm the target is running
List running containers and copy the exact name or ID:
$ docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Command}}'
CONTAINER ID NAMES STATUS COMMAND
abc123def456 example-app Up 2 minutes "/usr/local/bin/app"
The output is host-specific. If the target is absent, check stopped containers with docker ps -a. docker attach only attaches to a running container, and it follows the container's main ENTRYPOINT or CMD process, not an arbitrary process you choose later.
Checkpoint: set a shell variable only after checking the name visually:
CONTAINER='example-app'
docker inspect --format 'name={{.Name}} status={{.State.Status}}' "$CONTAINER"
Expected output includes status=running. If it does not, stop here. Use a separate, deliberate start or restart procedure rather than treating attach as a way to revive the container.
2. Attach without sending input
For a log-like view, leave standard input disconnected:
$ docker attach --no-stdin example-app
You will see output produced after the connection is made. A quiet screen does not necessarily mean that attach is stuck: the main process may simply have nothing to write. For a busy or performance-sensitive application, prefer docker logs. Attach uses a client-side buffer, so a slow connection can affect a process that writes heavily.
To leave this session, use the detach sequence described in the next step. If the process exits, attach exits as well and returns the container command's exit status where Docker can provide it.
3. Detach while leaving the container running
The default Docker detach sequence is Ctrl-p followed by Ctrl-q. Press the two combinations in order while the attach session has focus. Do not hold them as one chord.
$ docker attach example-app
application output appears here
read escape sequence
$ docker ps --filter name=example-app --format '{{.Names}} {{.Status}}'
example-app Up 4 minutes
The exact message and output vary by client and application. The important check is that the container remains listed as running after your terminal returns.
If the default sequence conflicts with an application or terminal workflow, choose a per-connection sequence:
$ docker attach --detach-keys='ctrl-@' example-app
The value format accepts a single letter, or ctrl- followed by one of the characters documented by docker attach --help, including lowercase letters, @, [, backslash, underscore and caret. Test an unfamiliar sequence on a disposable container first. A persistent default belongs in Docker's client configuration, which affects future commands and should be reviewed separately.
4. Treat Ctrl-c as a stop-risk
Warning
Do not press Ctrl-c merely to get your prompt back. The installed manpage describes it as stopping the container, and signal handling depends on the container's TTY and the signal-proxy setting. Current Docker documentation explains that the default --sig-proxy=true forwards signals such as SIGINT to the attached process. Either way, Ctrl-c is input with operational consequences, not a safe detach shortcut.
Before attaching to an important service, inspect its terminal settings and command:
$ docker inspect --format 'tty={{.Config.Tty}} stdin={{.Config.OpenStdin}} command={{json .Config.Cmd}}' example-app
tty=false stdin=false command=["/usr/local/bin/app"]
When you need a read-only observation session, use --no-stdin and avoid control keys. When you genuinely need interactive input, keep the session short and agree the stop procedure first.
5. Choose signal proxying deliberately
The --sig-proxy option is enabled by default. Set it explicitly when documenting an operational command:
$ docker attach --sig-proxy=false example-app
This prevents signals received by the Docker CLI from being proxied to the container process. It does not make the session read-only, and it does not prevent the application from exiting for its own reasons. It also does not change the container's configuration for later attaches.
Use --sig-proxy=false only when that signal boundary is understood. If the attached process needs terminal input, do not combine this option with an assumption that the application will behave like a shell. For a shell in a container, docker exec -it is usually the more precise tool because it starts a separate process instead of taking over the main process's streams.
6. Recover from a confusing session
If attach reports that the container is not running, inspect its final state and logs:
$ docker ps -a --filter name=example-app --format '{{.Names}} status={{.Status}} exit={{.State}}'
$ docker logs --tail 100 example-app
Do not restart automatically until you know whether the main process crashed, completed normally, or received a signal. If your terminal appears captured after a broken connection, press the detach sequence once, then check the Docker client prompt. Avoid sending repeated control characters to a service you have not identified.
If you created a disposable container while practising, remove only that named test container after confirming it is the correct target:
$ docker ps -a --filter name=attach-practice
$ docker container rm --force attach-practice
Destructive action
docker container rm --force stops and removes the named container. It does not remove its image, but data stored only in the container's writable layer is lost. Never substitute a production name.
Done means
- You verified the target name and confirmed its status is
running. - You can observe output with
--no-stdinwhen interactive input is unnecessary. - You can detach with Ctrl-p, Ctrl-q and verify the container stayed up.
- You treat Ctrl-c as a possible service-disrupting action.
- You understand the default signal proxy and can choose
--sig-proxy=falseintentionally. - You know when
docker logsordocker exec -itis a better fit.