Container Interaction

Container Interaction

Bitnesia • Sep 8, 2026 73 •ID

Just because a container is running does not mean our work is done. After docker run successfully creates a container, Sysadmins and DevOps Engineers still need to verify whether the application inside is running normally, inspect logs to track errors, or enter the container for direct debugging. Developers working on applications also frequently need to check the container contents, execute one-off commands for verification, or monitor resource utilization so the container does not overburden the development machine. This chapter covers four primary ways to interact with running containers: entering them via exec and attach, inspecting logs via docker logs, monitoring resources via docker top, and viewing real-time container statistics and events via docker stats and docker events.

8.1 Entering a Container

Docker provides two distinct commands to enter a running container: docker exec and docker attach. These two commands are often confused because both open interactive sessions; however, their underlying mechanics are significantly different and impact the active container differently.

8.1.1 Exec into a Container

The docker exec command runs a new process inside the namespace of an already running container, separate from the primary process (PID 1) currently active. Because it creates a new process, docker exec is safe to use at any time without interfering with the container primary process. First, set up an Nginx container as an example.

docker run -d --name demo-nginx nginx:1.27

Enter the container shell via docker exec using the -i (--interactive) and -t (--tty) options, exactly like the option combination in docker run.

docker exec -it demo-nginx sh

The terminal prompt changes, indicating that you are now inside the container shell. Try a few basic commands to ensure this session is truly connected to the container filesystem rather than the host machine.

ls /etc/nginx
cat /etc/os-release
exit

Type exit to exit the shell session. Unlike docker run -it, exiting a docker exec session does not stop the container, because the sh process executed via exec is merely an additional process, not the main process of the container. The demo-nginx container remains running even after its shell session is closed; verify this using docker ps.

docker ps --filter name=demo-nginx

docker exec does not always need to open an interactive session. For one-off commands, simply invoke the command directly without the -it options, which is useful, for example, to inspect the contents of a configuration file without entering the shell at all.

docker exec demo-nginx cat /etc/nginx/nginx.conf

The -u (--user) option is useful when you need to execute a command as a specific user inside the container, distinct from the default user used by the main process. Sysadmins and DevOps Engineers frequently use this when a container runs as a non-root user for security reasons, but temporary root access is required for debugging or installing additional tools.

docker exec -u root demo-nginx whoami

Try running docker exec against a stopped container to observe its error behavior. Stop the example container first, then try entering again.

docker stop demo-nginx
docker exec -it demo-nginx sh

Docker rejects the request with the error Error response from daemon: Container <container_id> is not running. This message clearly indicates that docker exec can only be used on containers with a status of truly running; if the container is stopped, there is no active process to attach a new process to.

8.1.2 Attach to a Container

Unlike docker exec which creates a new process, docker attach connects your terminal directly to the STDIN, STDOUT, and STDERR of the main process (PID 1) of the running container. Start the example container again, then try to attach.

docker start demo-nginx
docker attach demo-nginx

The terminal immediately displays the Nginx log output live, as if you were attached directly to its main process output. At this point, it is crucial to note the risk: because the --sig-proxy option defaults to true, pressing Ctrl+C in an attach session forwards the SIGINT signal to the main process of the container, which in many applications causes that process to exit, thereby stopping the container. This differs significantly from docker exec, which can be safely left at any time.

To exit an attach session without stopping the container, use the detach key sequence Ctrl-P followed by Ctrl-Q (this only works if the container was originally started with the -it option). Try this combination in the currently open attach session.

If you need to re-enter an 0attach session without the risk of signals killing the main process, add the --sig-proxy=false option so that Ctrl+C only closes the attach session on the client side without being forwarded into the container.

docker attach --sig-proxy=false demo-nginx

In practice, Sysadmins and DevOps Engineers prefer docker exec -it <container> sh over docker attach for routine debugging, specifically because the risk of accidentally terminating the main process via attach is practically eliminated with exec. docker attach is only truly needed when direct interaction with the main process of the container is required, such as an interactively started container via docker run -it that was accidentally detached.

Clean up the example container before moving to the next section.

docker rm -f demo-nginx

8.2 Viewing Container Logs

The docker logs command displays the output written by the container main process to STDOUT and STDERR, serving as the primary information source for tracing errors or monitoring application activity without entering the container. Prepare an Nginx container as an example, then send a few requests to generate log entries.

docker run -d --name demo-nginx -p 8080:80 nginx:1.27
curl http://localhost:8080

Display all logged output recorded since the container started.

docker logs demo-nginx
/docker-entrypoint.sh: Configuration complete; ready for start up
172.17.0.1 - - [08/Sep/2026:10:15:22 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.5.0" "-"

For logs that grow continuously in real-time, add the -f (--follow) option, similar to the behavior of tail -f on standard log files.

docker logs -f demo-nginx

Open another terminal, send a few additional requests, and observe new log lines appearing immediately in the terminal that is performing the follow. Press Ctrl+C to stop follow mode; this is safe and does not affect the container at all, because docker logs only reads recorded output rather than connecting directly to the main process like docker attach.

For logs that have accumulated extensively, the --tail option limits the number of recent lines displayed, avoiding the need to scroll through thousands of older log lines.

docker logs --tail 20 demo-nginx

The --since and --until options filter logs based on time ranges, accepting relative time formats such as 10m (the last 10 minutes) as well as absolute timestamps in RFC 3339 format.

docker logs --since 10m demo-nginx

Add the -t (--timestamps) option to include timestamps on every log line, which is useful when correlating error event times with logs from other systems.

docker logs -t --tail 5 demo-nginx

docker logs can only read logs through specific logging drivers, namely json-file (Docker's default driver), local, and journald. If a container runs with a different logging driver that does not support direct reading, such as syslog or fluentd, the docker logs command will fail with an error such as Error response from daemon: configured logging driver does not support reading. Check the logging driver used by a container via docker inspect.

docker inspect --format '{{.HostConfig.LogConfig.Type}}' demo-nginx

In production environments, logs displayed by docker logs will grow continuously over time when using the json-file driver without configured size limits (rotation), potentially filling up the host disk for containers that log heavily over long periods. Production Sysadmins and DevOps Engineers typically configure the max-size and max-file options on the json-file logging driver to automatically rotate old logs, rather than allowing log files to grow indefinitely.

Clean up the example container before proceeding.

docker rm -f demo-nginx

8.3 Monitoring Resource Usage

In addition to application logs, monitoring the processes and resources consumed by a container is equally critical, especially when diagnosing containers that feel slow or unresponsive. The docker top command displays a list of processes running inside a container, viewed directly from the perspective of the host because Docker containers share the same kernel as the host system.

docker run -d --name demo-nginx nginx:1.27
docker top demo-nginx
UID    PID    PPID   C    STIME   TTY   TIME       CMD
root   4821   4799   0    10:20   ?     00:00:00   nginx: master process nginx -g daemon off;
101    4867   4821   0    10:20   ?     00:00:00   nginx: worker process

The PID column above refers to the PID in the host namespace, not the PID inside the container, because docker top actually executes ps from the host side filtered for processes belonging to that container. This is useful for Sysadmins and DevOps Engineers who need to identify which container process is contributing to high CPU load at the host level without first entering the container.

docker top accepts additional options similar to the standard ps command in Linux, such as displaying memory usage columns.

docker top demo-nginx aux

If the container has stopped, docker top automatically fails because there are no active processes to inspect. Stop the example container first to observe this behavior.

docker stop demo-nginx
docker top demo-nginx

Docker returns the error Error response from daemon: Container <container_id> is not running, similar to the behavior of docker exec on a stopped container; both require an active process inside the container to function.

Start the example container again before continuing to the next section.

docker start demo-nginx

8.4 Container Stats and Events

docker top shows running processes, but it does not answer how much CPU, memory, or network bandwidth the container actually consumes. For this, Docker provides docker stats, which displays live resource metrics, and docker events, which streams real-time event logs from the Docker daemon.

8.4.1 Docker Stats

Run docker stats without arguments to view statistics for all currently running containers, continuously updated live much like top on Linux systems.

docker stats
CONTAINER ID   NAME         CPU %   MEM USAGE / LIMIT     MEM %   NET I/O          BLOCK I/O   PIDS
7a1b2c3d4e5f   demo-nginx   0.00%   3.406MiB / 7.762GiB   0.04%   1.24kB / 0B      0B / 0B     2

The MEM USAGE / LIMIT column shows the container memory usage relative to the allocated limit, while NET I/O and BLOCK I/O represent total network traffic and disk read/write operations since the container was started. The PIDS column tracks the number of active processes and threads inside the container, a metric useful for detecting fork bombs or processes reproducing uncontrollably within the container.

To monitor a specific container only, specify its name explicitly.

docker stats demo-nginx

Because docker stats streams continuously by default and locks the terminal, add the --no-stream option when you only need a single metric snapshot, such as when running inside automated scripts that should not block indefinitely.

docker stats --no-stream demo-nginx

The --format option customizes displayed columns using Go templates, which is useful when statistics need further processing by external monitoring tools.

docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

In practice, note that on Linux, the docker stats CLI calculates MEM USAGE by subtracting page cache usage from the total container cgroup memory so that the metric reflects memory actively used by the application rather than reclaimable kernel cache. Nevertheless, this figure may still differ from application-level profiling tools because cgroups calculate shared library memory and buffers differently from application internal memory trackers. Do not jump to conclusions regarding memory leaks based solely on rising MEM USAGE without conducting deeper investigation via application-level profiling tools.

8.4.2 Docker Events

docker events displays a real-time stream of events from the Docker daemon, recording state changes occurring on containers, images, volumes, or networks on your Docker host. Run the following command in one terminal to start monitoring.

docker events

Open another terminal, perform a few actions on the example container, and observe the events appearing in the docker events terminal.

docker stop demo-nginx
docker start demo-nginx
2026-09-08T10:25:01.123456789Z container die 7a1b2c3d4e5f (image=nginx:1.27, name=demo-nginx)
2026-09-08T10:25:01.234567890Z container stop 7a1b2c3d4e5f (image=nginx:1.27, name=demo-nginx)
2026-09-08T10:25:05.345678901Z container start 7a1b2c3d4e5f (image=nginx:1.27, name=demo-nginx)

Press Ctrl+C to stop monitoring; like docker logs -f, this has no impact on the container because docker events only reads the daemon event stream without connecting to container processes.

The --filter option narrows down displayed events, for example, limiting to container events belonging to a specific container.

docker events --filter container=demo-nginx --filter event=die

Like docker logs, the --since and --until options are useful for querying past events rather than only live events triggered after execution.

docker events --since 30m --until 0m

In operational environments, docker events is a staple tool for Sysadmins and DevOps Engineers to build simple audit trails or trigger external automation, such as scripts that automatically alert the team when a die or oom event (container killed by the kernel due to running out of memory) occurs on a critical production container. Because docker events only shows events occurring after the command is invoked (unless bounded by --since), ensure this monitoring process runs continuously in the background so no critical events are missed.

Clean up the example container used throughout this chapter.

docker rm -f demo-nginx
CommandFunction
docker exec -it <container> shRuns a new process inside a running container
docker attach <container>Attaches the terminal to the primary process (PID 1) of the container
docker logs -f <container>Displays and follows container STDOUT/STDERR output
docker top <container>Displays processes running inside the container
docker stats <container>Displays live CPU, memory, network, and disk usage statistics
docker eventsStreams real-time events from the Docker daemon