skip to content

questions

4

A container vanishes from `docker ps` seconds after `docker run` — what do you check first?

level: juniorimportance: must knowfreq 86%

answer

  1. The container did not disappear
  2. Drop the running-only filter
  3. Status column is already a diagnosis
  4. Stopped containers still have logs
  5. --rm deletes the evidence

basics

~20 s

Run docker ps -a: the container is still listed, with a STATUS such as Exited (1) 20 seconds ago that says whether it ran and died or never started. Then docker logs on that container shows what it printed.

solid answer

~40 s

`docker ps` only shows running containers, so the first move is `docker ps -a`, which lists the dead one with its STATUS column: `Created` means the runtime never started the process, `Exited (N)` means it ran and stopped, `Restarting (N)` means a restart policy is looping it. Next, `docker logs <container>` replays everything the process wrote to stdout and stderr before it died — add `--timestamps` and `--tail 50` on a noisy container. If the logs are empty, go to `docker inspect` for `.State.ExitCode`, `.State.OOMKilled` and `.State.Error`. The one thing that destroys this whole ladder is `--rm`: it deletes the container the instant it exits, taking its logs and inspect record with it, so reproduce without `--rm`.

code

bash · 3 lines
bash
docker ps -a --filter name=pdfsign
docker logs --timestamps --tail 50 pdfsign-api
docker inspect --format '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}' pdfsign-api

go deeper

for a junior

Memorise the three commands in order: docker ps -a, docker logs <container>, docker inspect <container>. Be ready to say why docker ps alone shows nothing and why --rm is a bad idea while debugging.

for a middle

Explain what each STATUS value means — Created, Exited, Restarting — and where the log stream actually comes from: the daemon captures the main process's stdout and stderr through the logging driver, not a file inside the container.

for a senior

Show a routing habit: which observation sends you to logs, which to inspect, which back to the image. Mention the buffering trap and how you make a service reproduce its failure loudly instead of silently.

for a principal

Own the argument that crash evidence must survive the crash: containers not removed on exit during incidents, applications logging to stdout by convention, and log retention long enough that the first failure is still readable when someone looks.

A container that disappears from `docker ps` has not vanished — `docker ps` is a filter that shows only containers whose status is *running*. The container object still exists on the host until something removes it, and every piece of evidence you need is hanging off that object. Triage is therefore a fixed ladder: list, read the status, read the logs, then inspect. ## Step 1 — `docker ps -a` `-a` (`--all`) drops the running-only filter, so the exited container reappears with a STATUS string that is already a diagnosis: - **`Created`** — the container object exists but its process never ran. Something failed in the runtime before the first instruction executed: a binary that is not in the image, a missing bind-mount source, an invalid `--user`. Such a container produces **no application logs at all**, and the `docker run` invocation itself printed the error. - **`Exited (N) 12 seconds ago`** — the process ran and returned status *N*. There will usually be logs. - **`Restarting (N)`** — a restart policy is putting it back, so you are watching a loop rather than a single death. - **`Up 4 seconds`** followed a moment later by `Exited` — the process starts and dies repeatedly. Narrow the list with filters instead of scrolling: `docker ps -a --filter name=pdfsign --filter status=exited`, and shape the output with `--format` when you want just names and statuses. ## Step 2 — `docker logs` `docker logs <container>` works on a **stopped** container exactly as it does on a running one, because the default `json-file` logging driver has already written the stream to disk under the container's directory. It replays stdout and stderr together, in the order the daemon received them. Useful flags: `--timestamps` (each line gets an RFC3339 timestamp, which is how you correlate the death with an external event), `--tail 100` (the end is where the crash is), `--since 10m`, and `--follow` when you want to watch the next attempt live. Empty output is itself a signal, and it has three common causes worth separating: the process never ran (status `Created`), the process logs to a *file inside the container* rather than stdout, or the runtime buffered a partial line that was lost when the process was killed. Interpreted-language servers are the classic buffering case: a Django application served by gunicorn will not flush an unterminated line, and Python buffers stdout when it is a pipe rather than a terminal, so a crash traceback can be swallowed. Setting `PYTHONUNBUFFERED=1` — or, generically, running the process with unbuffered output — is a standard fix that makes the next reproduction talk. ## Step 3 — `docker inspect` When logs do not explain it, `docker inspect <container>` returns the full container JSON, and `--format` pulls out just the fields that matter: `.State.ExitCode`, `.State.OOMKilled`, `.State.Error`, `.State.StartedAt` and `.State.FinishedAt`. The gap between the last two tells you whether the process lived for milliseconds (it never got past startup) or for minutes (it got through startup and then hit something). ## A worked example A PDF-signing service, `pdfsign:1.9.3`, is started with `docker run -d --name pdfsign-api pdfsign:1.9.3`. The command prints a container ID and returns; `docker ps` shows nothing. `docker ps -a` shows `Exited (3) 4 seconds ago`. `docker logs pdfsign-api --timestamps` shows two lines of gunicorn boot output and then a traceback about a signing key file that is not present. Total elapsed triage: two commands. Had the operator started it with `--rm`, both commands would have returned nothing at all, and the usual next step — guessing — would have begun. ## Traps that waste the first ten minutes **`--rm`** removes the container as soon as it exits. It is right for one-shot commands and wrong for anything you are debugging: rerun without it. **Detached mode** hides the failure: `docker run -d` prints an ID and returns zero even when the process dies a moment later, so never treat a successful `docker run -d` as a successful start — re-run in the foreground, or check `docker ps -a` immediately. **Grabbing the wrong container**: after several attempts you may have five similarly named dead containers; take the ID from `docker ps -a` rather than assuming the name still resolves to the interesting one. And **reading the daemon's error as an application error**: a message from `docker run` beginning `docker: Error response from daemon:` is the engine telling you it could not start the container, which is a different class of problem from an application that started and then threw. The habit worth building is that every crash question is answered by *evidence*, and the evidence lives in a known place: status in `docker ps -a`, output in `docker logs`, structured facts in `docker inspect`. Reach for those three before forming any theory.

  • Why does `docker run --rm` make this triage much harder?
    `--rm` tells the daemon to delete the container object the moment it exits. That deletion takes the json-file log and the inspect record with it, so `docker ps -a` shows nothing, `docker logs` errors with 'No such container', and there is nothing left to inspect. Reproduce the failure without `--rm`, or capture output in the foreground, before you start theorising.
  • How do you tell a container that never started from one that started and then crashed?
    A container that never started sits at status `Created`, has no application log output, an empty `.State.StartedAt`-to-`.State.FinishedAt` window, and usually a message in `.State.Error` from the runtime. One that started and crashed shows `Exited (N)`, has a real StartedAt and FinishedAt, and normally printed something before dying. The first is an engine or image problem; the second is an application problem.
  • `docker logs` shows nothing but the container clearly ran for two seconds. What is the most common cause?
    The process wrote to a file inside the container instead of stdout/stderr, or its runtime buffered output that was never flushed before the crash. Docker only captures the main process's stdout and stderr streams. Fix it at the source — log to stdout, or disable buffering, for example with `PYTHONUNBUFFERED=1` for a Python service — and for the run you already have, copy the file out of the stopped container.

docker ps is the arrivals board for flights currently in the air; docker ps -a is the full log including the ones that never took off, and docker logs is the cockpit voice recorder for each of them.

saying these in an interview costs you the question

  • Says the container is gone because docker ps does not list it
  • Debugs with --rm and then wonders where the logs went
  • Treats a successful docker run -d as a successful start
  • Thinks docker logs only works on running containers
  • Jumps straight to editing the Dockerfile before reading any output
  • Reads a daemon error message as an application stack trace

context

open as a page

Which `docker inspect` fields explain why a container exited, and how do you print just them?

level: middleimportance: should knowfreq 61%

basics

~10 s

Read .State.ExitCode, .State.OOMKilled, .State.Error, .State.StartedAt and .State.FinishedAt, plus the top-level .RestartCount — RestartCount sits outside State. Print them with docker inspect --format and a Go template instead of paging the whole JSON.

open as a page

`docker logs` prints nothing for a container that exits instantly — how do you get evidence?

level: seniorimportance: should knowfreq 47%

basics

~20 s

Empty output has three causes: the process never started, it logged to a file instead of stdout, or the log driver cannot be read back. Check the status first, then open the image with docker run --entrypoint sh.

open as a page

A Docker container has restarted 47 times overnight — what evidence about the earlier runs survives?

level: seniorimportance: nice to knowfreq 31%

basics

~20 s

A restart policy reuses the same container, so docker logs still holds every earlier run's output, separated only by timestamps. docker inspect describes just the latest run apart from RestartCount, and log rotation may have deleted the first failure.

open as a page