Skip to content

Interactive vs Detached Mode


Running a container is easy. Knowing how it should run — whether it should hand you a shell, sit quietly in the background, or let you pop in and out without disturbing it — is where most people get tripped up early on.

We here will walks through the flags and commands that control that behavior. By the end, you’ll know exactly which one to reach for, and why mixing them up can accidentally take down a running container.

Docker Interactive Mode

Before talking about interactive mode, let’s run a container in the default way — not interactive at all:

docker container run ubuntu echo "From Non-Interactive Mode!"

You get the output:

From Non-Interactive Mode!

And you immediately get your shell back. That’s non-interactive mode — you never actually get a chance to interact with the container. Docker starts the container, runs the command, prints the output, and exits. There’s no conversation happening, just a one-way instruction.

Interactive Mode

To run a container in interactive mode, you use the -i (or --interactive) flag. But flag alone isn’t enough — you also need a command that’s actually capable of being interacted with. Running echo won’t help, because echo doesn’t wait for input; it just prints and exits. So this:

docker container run -i ubuntu echo "From Non-Interactive Mode!"

behaves exactly the same as before. You still get your shell back immediately.

Now, Ubuntu ships with bash, and bash does give you an interactive shell. Combine that with -i:

docker container run -i ubuntu bash

This time you’re dropped into the container’s shell:

whoami
root
hostname
859a96b954d5
exit

Here I ran a couple of commands inside the container — whoami and hostname — and then exited with exit.

Important

exit or Ctrl+D gets you out of container but Docker stops your container immediately.
If you want to get out of your container without stopping it use Ctrl+P and Ctrl+Q combo instead. Docker then sends your container in background.

Interactive Mode With TTY

-i lets you interact with the container, but it doesn’t give you that “real terminal” feel — no prompt, no colors, no sense of actually being inside a shell session. For that, you pair it with the -t option, which allocates a tty (pseudo-terminal).

docker container run -it ubuntu bash

Now you get a proper prompt with a nice PS1 string — notice how much more like “being inside” the container this feels, compared to plain -i:

root@ab11f6923029:/# hostname
ab11f6923029
root@ab11f6923029:/# exit
exit

I ran hostname and then exited out.

What exactly is a tty?

TTY stands for teletypewriter — a term that goes back to actual mechanical typewriter terminals used to interact with early computers. Today it just refers to a text-based terminal interface. For practical purposes, you can treat tty as a synonym for terminal.

Together, -it (short for -i -t) is the combination you’ll use almost every time you want to drop into a container and work inside it interactively — think of it as your “SSH into the container” flag.

Docker Detached Mode: Sending a Container to the Background

Some containers — or commands run at container startup — hold on to your terminal for as long as they run. sleep is a good example:

docker container run ubuntu sleep 300

sleep 300 running inside the container occupies your terminal for a full 300 seconds (5 minutes). Your shell is stuck until the command finishes. If you want the container to keep running in the background while you immediately get your shell back, that’s detached mode, using -d:

docker container run -d ubuntu sleep 300

Running in detached mode prints the container ID instead of blocking your terminal:

69ba11a9d74efcf197d449783415c7b0d6fffc4e61db79a806937b3e501be74b

You can confirm it’s running with:

docker container ls

Output:

CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
6d0db26291cd   ubuntu    "sleep 300"   8 seconds ago   Up 7 seconds             exciting_keldysh

Running Commands on Detached Containers

While the container is already running in the background, you can run additional commands inside it using exec. The correct syntax is docker container exec <container-id> <command>:

docker container exec 6d0db26291cd hostname

This gives you the container’s hostname:

6d0db26291cd
Why does the hostname match the container ID?

Docker uses the container ID as the container’s hostname by default. That’s why hostname inside the container returns the same (truncated) ID you see in docker container ls.

You’ll often combine exec with -it to get an interactive shell into an already-running container, without touching its main process:

docker container exec -it 6d0db26291cd bash

Attaching to Detached Containers: Bringing It Back to the Foreground

You can also bring a detached container’s main process back to the foreground with attach:

docker container attach 6d0db26291cd

Since we used sleep 300 as the main process, attaching just holds your terminal until sleep finishes — because that’s literally what sleep does. If it had been an nginx container instead, you’d see live web server logs streaming in your terminal instead of dead silence.

After the 300 seconds are up:

docker container ls

…shows nothing. The container has exited and no longer appears in the default (running-only) list. To see it anyway, add -a:

docker container ls -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                        PORTS     NAMES
6d0db26291cd   ubuntu    "sleep 300"   About a minute ago   Exited (0) 26 seconds ago               exciting_keldysh

It confirms that container 6d0db26291cd, started with sleep 300, Exited 26 seconds ago — visible in the STATUS column.

exec vs attach: They’re Not the Same Thing

It’s easy to lump these two together since both let you “get into” a running container, but they behave very differently under the hood:

  • attach connects your terminal to the container’s main process (PID 1) — the exact same process that’s already running.
  • exec starts a brand-new process inside the container’s namespaces, alongside the main process.
    flowchart LR
    A["Running Container<br/>(main process, PID 1)"] --> B["docker container attach"]
    A --> C["docker container exec bash"]
    B --> D["Connects directly to<br/>the existing main process"]
    C --> E["Spawns a new process<br/>next to the main process"]
    D --> F["Ctrl+C may stop<br/>the main process"]
    E --> G["Exiting the shell<br/>leaves main process untouched"]
  

This distinction matters more than it looks. If you attach to a container and hit Ctrl+C, you can accidentally send a termination signal to the main process and stop the container entirely — not something you want to do to a production database by accident. exec, on the other hand, gives you a disposable side-shell: you can poke around, run diagnostics, and exit without ever touching the process that’s actually keeping the container alive.

As a rule of thumb: use exec when you want to look inside a running container, and reserve attach for when you genuinely want to reconnect to the main process’s own input/output stream (for example, to see live logs or respond to a prompt the main process itself is printing).

When to Choose Interactive and Detached Mode (Real World)

Choose interactive mode (-it) when:

  • You’re exploring a base image for the first time and want to poke around inside it.
  • You’re debugging — installing packages, checking config files, testing commands before scripting them.
  • You’re running something that genuinely expects human input, like a database CLI (psql, mysql) or a REPL (python, node).
  • You’re building and testing a Dockerfile step by step, and want to confirm commands work before baking them in.

Choose detached mode (-d) when:

  • You’re running a long-lived service — a web server, an API, a database, a message queue — that should keep running in the background indefinitely.
  • You don’t need to babysit the process; you just need it up and reachable (via exposed ports, logs, or exec).
  • You’re running this in a production-like setting, where a dropped SSH session or closed terminal shouldn’t take your container down with it.
  • You want to run multiple containers side by side without dedicating a terminal tab to each one.

A simple way to remember it: interactive mode is for conversations, detached mode is for coworkers. You talk to an interactive container. A detached container just does its job quietly in another room, and you check in on it with logs, exec, or attach only when you need to.

    flowchart TD
    Start["Do you need to talk to the container right now?"] -->|Yes, exploring/debugging| Interactive["Use -it<br/>e.g. docker container run -it ubuntu bash"]
    Start -->|No, it should run on its own| Detached["Use -d<br/>e.g. docker container run -d nginx"]
    Detached --> Check{"Need to check on it later?"}
    Check -->|Peek inside without risk| Exec["docker container exec -it &lt;id&gt; bash"]
    Check -->|Reconnect to main process output| Attach["docker container attach &lt;id&gt;"]
  

Quick Reference

Flag / CommandWhat it does
-iKeeps STDIN open so you can send input to the container
-tAllocates a pseudo-terminal (tty) for a proper prompt
-itCombines both — the standard flag set for interactive shells
-dRuns the container in the background, returns shell instantly
docker container exec <id> <cmd>Runs a new process inside an already-running container
docker container attach <id>Reconnects your terminal to the container’s main process
Last updated on