The first container I ever ran, I ran in the foreground, watched its logs scroll by, and then panicked slightly when closing my terminal killed it. That’s when I learned about detached mode — the difference between a container that occupies your terminal session and one that runs quietly in the background, exactly the way a real service should.
Foreground vs. Detached Mode
By default, docker run attaches your terminal to the container’s standard output and keeps it in the foreground:
docker run nginx:latest
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/07/29 11:02:03 [notice] 1#1: nginx/1.27.0
2026/07/29 11:02:03 [notice] 1#1: start worker processes
The terminal is now occupied — pressing Ctrl+C sends SIGINT to the container and stops it. That’s fine for a quick test, but useless for anything long-running.
Running Detached
Adding -d (or --detach) starts the container and immediately returns control of the terminal:
docker run -d --name web-bg -p 8080:80 nginx:latest
Expected output:
c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
Docker prints only the full container ID and returns me straight to my shell prompt. The container keeps running independently of the terminal session that started it.
Verifying It’s Running
docker ps
CONTAINER ID IMAGE COMMAND STATUS PORTS NAMES
c3d4e5f6a7b8 nginx:latest "/docker-entrypoint.…" Up 5 seconds 0.0.0.0:8080->80/tcp web-bg
curl http://localhost:8080
<!DOCTYPE html>
<html>
<head><title>Welcome to nginx!</title></head>
...
Viewing Output From a Detached Container
Since I’m not attached to the container’s stdout, logs go through Docker’s logging driver instead. I retrieve them on demand:
docker logs web-bg
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/07/29 11:03:10 [notice] 1#1: nginx/1.27.0
2026/07/29 11:03:10 [notice] 1#1: start worker processes
Follow logs live, similar to tail -f:
docker logs -f --tail 50 web-bg
--tail 50 shows only the last 50 lines before following new output, which is useful for busy containers where I don’t want to scroll through megabytes of historical logs.
Attaching to an Already-Running Detached Container
If I do want to interact with a detached container’s main process directly:
docker attach web-bg
I need to be careful here: pressing Ctrl+C while attached to certain processes sends SIGINT and can stop the container, exactly like foreground mode. Detaching without killing the container requires the escape sequence Ctrl+P, Ctrl+Q instead.
For most interactive work, I use docker exec instead, which starts a brand-new process inside the container’s namespaces without touching the main process at all:
docker exec -it web-bg /bin/bash
root@c3d4e5f6a7b8:/#
Detached Mode With docker compose
The same -d flag applies to Compose:
docker compose up -d
[+] Running 3/3
✔ Network myapp_default Created
✔ Container myapp-db-1 Started
✔ Container myapp-web-1 Started
Compose logs work the same way:
docker compose logs -f web
Internal Working: What -d Actually Changes
The -d flag doesn’t change how the container’s process runs internally — the container still starts, gets its namespaces and cgroups set up, and executes its CMD/ENTRYPOINT exactly the same way. What changes is purely on the client/daemon communication side: with -d, the Docker CLI issues the create-and-start API calls, then disconnects from the container’s I/O streams immediately, printing only the container ID. Without -d, the CLI keeps a streaming connection open to the daemon, relaying stdout/stderr back to your terminal and forwarding signals like SIGINT from your terminal to the container.
Under the hood, Docker’s logging driver (json-file by default) is what actually captures a detached container’s output so docker logs can retrieve it later — that log driver is active regardless of whether you’re attached, so nothing is lost when running detached.
Networking Notes
Detached mode has no effect on networking — port publishing (-p 8080:80), custom networks, and DNS resolution between containers work identically whether the container runs attached or detached. The only relevant interaction is that health checks and orchestration tools (like Compose or Kubernetes) assume long-running, backgrounded processes, which is exactly the shape detached containers provide.
Storage Notes
Detached mode doesn’t affect the container’s filesystem or volumes. Whether attached or not, writes to the writable layer or mounted volumes behave identically.
Security Considerations
- A container running detached is just as accessible via
docker execas one running attached — detached mode is not an isolation boundary, only a terminal-attachment convenience. - Because detached containers run unattended, make sure meaningful health checks and restart policies are configured, since no human is watching the terminal for crashes:
docker run -d --name web-bg \
--restart unless-stopped \
--health-cmd="curl -f http://localhost/ || exit 1" \
--health-interval=30s \
-p 8080:80 nginx:latest
Troubleshooting
Container exits immediately even with -d Detached mode doesn’t prevent a container from exiting if its main process finishes or crashes right away. Check:
docker ps -a
docker logs web-bg
“Cannot attach to a stopped container” docker attach only works on running containers. If the container already exited, use docker logs to inspect what happened instead.
Forgot which containers are running detached
docker ps
shows every currently running container regardless of attach state.
Monitoring
docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT NET I/O
c3d4e5f6a7b8 web-bg 0.03% 3.4MiB / 1.944GiB 1.4kB / 0B
For centralized monitoring of many detached containers, I typically forward logs to a driver like json-file with rotation configured, or ship them to an external system:
docker run -d --log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
--name web-bg -p 8080:80 nginx:latest
Best Practices
- Use
-dfor anything meant to run as a long-lived service. - Pair detached mode with
--restartpolicies so containers recover from crashes without manual intervention. - Use
docker execrather thandocker attachfor interactive debugging to avoid accidentally killing the main process. - Configure log rotation (
max-size,max-file) so detached containers don’t silently fill up disk over weeks of uptime. - Set up
HEALTHCHECKso orchestration tools can detect a hung detached container even if its process technically hasn’t exited.
Summary
Detached mode is less about changing how a container runs and more about changing how your terminal relates to it. The container’s process, namespaces, and logging behave identically either way — -d simply lets Docker hand control back to the shell immediately, while docker logs, docker exec, and health checks give me everything I need to observe and manage it afterward.
References
- Docker run reference: https://docs.docker.com/reference/cli/docker/container/run/
- Docker logs documentation: https://docs.docker.com/reference/cli/docker/container/logs/
- Docker restart policies: https://docs.docker.com/engine/containers/start-containers-automatically/
- Docker Compose CLI reference: https://docs.docker.com/reference/cli/docker/compose/up/