1.5Observing and debugging: logs, exec, inspect
The essentials in 30 seconds
- logs: listening to the patient: docker logs bdd reads the journal, -f follows it live, --tail 50 takes only the end — a looping container always tells its cause.
- exec: going in to check: docker exec -it web sh opens a shell in the living (file, ping, env) — diagnosis, never lasting installation.
- ps → logs → exec/inspect: docker ps -a gives the state and exit code, inspect reveals everything (variables, mounts, networks) — without guessing.
Running mini-case — Idir autopsies a silent web
On demo day, Idir's web stops answering. Instead of recreating everything blindly, he applies the method: docker ps -a shows an Exited (1), docker logs web blames a port already in use, docker inspect web confirms the publishing conflict. He frees the port, relaunches — the page is back. Five minutes, zero guessing: his manager mostly remembers that Idir named the cause before fixing.
End of cases 1.1-1.4 — Idir closes the level: diagnosing before fixing.
1. logs: listening to the patient
docker logs bdd reads the journal, -f follows it live, --tail 50 takes only the end. A container that restarts in a loop always tells its cause in its logs (missing password, busy port, volume at the wrong path).
On chatty services, limit with --tail: read the end, not kilometers. If logs is empty, the app may log elsewhere (internal file: go in with exec) or die before writing (inspect + config).
2. exec: going in to check
docker exec -it web sh opens a shell in the living: checking a file, testing a connection (ping bdd), reading a variable (env). For a one-shot without shell: docker exec web ls /usr/share/nginx/html. Nothing is durably installed this way: it is diagnosis.
Editing by hand in the container is lost at the next run: exec observes, it does not durably fix.
3. inspect and ps: the identity record
docker ps -a gives the state (Up, Exited, Restarting) and the exit code. docker inspect reveals everything: command, variables, mounts, networks, ports. Method: ps → logs → exec/inspect, in that order, without guessing.
And note the real cause, not the symptom: « port already in use » rather than « it does not work ».
The loop re-creator (never do this)
Moral: recreating without reading means losing seven times to the same log line.
🔎 Concrete example — 🔎 Concrete example — A web that does not answer
The autopsy of Idir's silent web, step by step.
docker ps -a # Exited (1)? Restarting?
docker logs web # e.g.: port already in use
docker inspect web # check ports and networks
docker exec -it web sh # search from the inside
Reading: state guides, logs accuse, inspection confirms.
Lesson: 90% of outages are solved without recreating blindly.
Section vocabulary
- logs
- The journal captured by the daemon; read with -f (live) and --tail (end).
Simple example: docker logs web --tail 30 reveals the busy port at Idir's.
What it is not: a file you edit by hand.
Reflex: always read before recreating.
- exec
- Running a command in a running container (shell with -it or one-shot).
Simple example: docker exec -it web sh to search the running web.
What it is not: creating a new container (run).
Reflex: exec = running; stopped = inspect or run --rm.
- inspect
- The complete JSON record of a container, image or network (variables, mounts, ports).
Simple example: docker inspect web confirms the port conflict.
What it is not: a guess about the configuration.
Reflex: the real config, not the one you believe.
- Exit code
- The 0 (OK) or non-zero (error) left by the process, visible in ps -a.
Simple example: Exited (1) points Idir to the logs.
What it is not: a port number.
Reflex: non-zero = read the logs at once.
In practice — In practice — Guided autopsy
- Deliberately launch a misconfigured container (wrong -e).
- Note its exact state with ps -a.
- Read its last 30 log lines and name the cause.
- Confirm with inspect (variables, mounts), then fix.
Script ready to say — autopsy in 5 minutes (30 s)
« My container is Exited (1): I read its last thirty log lines, I name the cause — port already in use. I confirm with inspect: ports and networks. I fix the cause, not the symptom, and I note it. »
Say while chaining ps, logs --tail then inspect; show the named cause before the fix.
Copy-paste template — autopsy checklist
docker ps -a # 1. STATE: Up? Exited (code)? Restarting?
docker logs NOM --tail 50 # 2. CAUSE: read the end, name it (port, -e, volume)
docker inspect NOM # 3. PROOF: variables, mounts, networks, ports
docker exec -it NOM sh # 4. if RUNNING: search (file, ping, env)
# 5. FIX the cause, NOTE it (not the symptom). Never recreate blindly.
Idir's silent web
As above: Exited (1) → logs → busy port → inspect → freeing → relaunch. Five minutes, zero guessing.
Database in Restarting
Restart loop: the logs hold the cause (often missing -e or wrong volume path) — read before acting.
Empty logs
App logging to an internal file: go in with exec to read it, or inspect + config if the container dies before writing.
One-shot without shell
docker exec web ls /usr/share/nginx/html: checking content without opening a shell — fast and risk-free.
✓ Best practices
- Always read the logs before recreating.
- Limit with --tail on chatty services.
- Note the real cause (not the symptom).
✗ Common pitfalls
- Recreating in a loop without reading (same error).
- Editing by hand in the container (lost at next run).
- Confusing exec (running) with run (new).
Key takeaways
- ps gives the state, logs the cause.
- exec goes in, inspect reveals everything.
- The ps → logs → exec/inspect order never changes.
- Fix the cause, not the symptom.
48h challenge — apply tomorrow
Deliberately sabotage a container (wrong -e), note its ps -a state, read 30 log lines, name the cause, confirm via inspect — then fix and note.
- I note the exact state (ps -a) before any hypothesis.
- I read the logs to name the cause.
- I confirm via inspect/exec and fix the cause.
Frequently asked questions
logs is empty, what to do?
Either the app logs elsewhere (internal file: go in with exec), or the container dies before writing (inspect + config). Also check the log driver.
exec refuses: 'container not running'?
Normal: exec requires a running container. Start it, or use run --rm for a throwaway inspection of the image.
A container is 'Restarting'. First reflex?