Inspecting Docker Containers and Processes
How to answer the four questions you ask when something is wrong: what state is it in, what is it printing, what is it running, and what is it consuming. Every command below was run against a live nginx container.
Containers and Images Guide 7 of 46 Beginner
- OSUbuntu 26.04 LTS (resolute)
- Docker Engine29.7.2
- Shellbash
- Architectureamd64
- TimeAbout 12 min
- Reviewed20 August 2026
Tested on the versions above. PIDs, IP addresses, timestamps and memory figures change on every run. Match the shape of the output, not the exact strings.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| DOCKER01 | 192.168.0.21 | Ubuntu 26.04 LTS | Docker Host | 2 Core | 4 GB | 50 GB |
Before you start
- A running container to inspect.
docker run -d --name cg-web -p 8080:80 nginx:alpinegives you one. - Comfort with
docker psanddocker run- guides 3 and 4 in this path.
-
What state is it in?
docker inspectholds the authoritative record. Three fields answer most questions: the status, when it started, and how many times it has restarted. A restart count climbing on its own is the signature of a crash loop, and it is invisible indocker psbecause the container keeps reappearing asUp.bash Example session docker inspect cg-web --format "{{.State.Status}} started={{.State.StartedAt}} restarts={{.RestartCount}}"running started=2026-08-20T05:22:55.200044778Z restarts=0Expected resultStatus
running, a start timestamp, and a restart count.Success condition
restarts=0. Anything above zero on a container you did not restart yourself means it has been failing and being brought back. -
What is it printing?
Logs are the container's stdout and stderr.
--taillimits how far back you look and--timestampsprefixes each line with when Docker received it, which matters when you are correlating against another system's clock. Add-fto follow live.bash Example session docker logs --tail 3 --timestamps cg-web2026-08-20T05:22:55.324669532Z 2026/08/20 05:22:55 [notice] 1#1: start worker process 302026-08-20T05:22:55.325074936Z 2026/08/20 05:22:55 [notice] 1#1: start worker process 312026-08-20T05:22:55.357433243Z 172.17.0.1 - - [20/Aug/2026:05:22:55 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.18.0" "-"Expected resultThree lines, each with a Docker timestamp followed by the application's own log line.
Success conditionYou see recent activity. If a container exited, its logs remain readable until the container is removed - that is where the reason will be.
-
What is it actually running?
docker toplists the processes inside the container as the host sees them. Two things are worth noticing: the PIDs are host PIDs, not the PID 1 the container sees internally, and the user column shows the real account each process runs as. Here nginx starts as root then drops its workers to an unprivileged user.bash Example session docker top cg-webUID PID PPID C STIME TTY TIME CMDroot 3633 3610 0 05:22 ? 00:00:00 nginx: master process nginx -g daemon off;pollina+ 3720 3633 0 05:22 ? 00:00:00 nginx: worker processExpected resultA master process and one or more workers. Output is abridged - the real listing includes every worker.
Success conditionYou can see the process tree. If only one unexpected process is listed, the container may be running something other than what you intended - check
docker inspect --format "{{.Config.Cmd}}". -
What is it consuming?
docker statsstreams live resource usage.--no-streamtakes one sample and exits, which is what you want in a script or a guide. The memory limit shown is the host's total when no limit has been set on the container - that is worth knowing, because an unlimited container can consume everything the host has.bash Example session docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" cg-webNAME CPU % MEM USAGE / LIMIT NET I/Ocg-web 0.00% 10.78MiB / 3.319GiB 1.51kB / 1.68kBExpected resultOne row of live figures. An idle nginx uses almost no CPU and around 10 MiB.
Success conditionYou get a sample and the command exits. If the LIMIT column shows the host's full memory, no limit is set on this container.
-
Look inside without restarting anything
When the outside view is not enough, run a command inside. This is read-only investigation - checking a version, listing a config directory, reading a file the application uses.
bash docker exec cg-web nginx -vnginx version: nginx/1.31.4docker exec cg-web sh -c "ls /etc/nginx/conf.d"default.confExpected resultThe version banner and the directory listing.
Success conditionBoth commands return. If exec fails with
No such container, the container has stopped - exec only works on running containers. -
Where is it reachable?
docker portreports the published mappings without you having to parse inspect output. Both an IPv4 and an IPv6 mapping appear because Docker publishes on both families by default.bash docker port cg-web80/tcp -> 0.0.0.0:808080/tcp -> [::]:8080Expected resultOne line per published port per address family.
Success conditionThe container port appears on the left and the host binding on the right. Empty output means nothing was published - the container is only reachable from other containers.
Troubleshooting
A docker inspect --format expression fails with a template parsing error
Why: The format string is Go template syntax, and shell quoting frequently mangles it. Ranges over maps are especially easy to break.
Fix:Start from a simple field and build up, and prefer a purpose-built command where one exists -
docker portinstead of ranging over.NetworkSettings.Ports. This exact error was hit while writing this guide.bash docker inspect cg-web --format "{{range $p, $c := .NetworkSettings.Ports}}{{$p}}{{end}}"template parsing error: template: :1: unexpected "," in range# use the purpose-built command instead:docker port cg-web80/tcp -> 0.0.0.0:8080docker logs shows nothing at all
Why: The application writes to a file inside the container rather than to stdout, so Docker never sees it. This is common with software not packaged for containers.
Fix:Read the file directly with exec, or reconfigure the application to log to stdout, which is the container convention.
bash docker exec cg-web sh -c "ls -l /var/log/nginx/"# nginx images symlink these to stdout/stderr, which is why docker logs works