BeginnerLesson 4 of 16

▶️ Running, Inspecting and Managing Containers

Master the container lifecycle — run, stop, inspect, exec into, read logs, and clean up. These are the daily tools every DevOps engineer uses.

🧒 Simple Explanation (ELI5)

Running a container is like starting a process on demand. You start it, it runs your app, you can peek inside it like opening a window into a room, and when done, you shut it off and clean up. The key skill here is knowing which command does what — and how to debug when things go wrong.

🔧 Container Lifecycle

Container Lifecycle States
Image
docker run
Running
docker stop
Stopped
docker rm
Deleted

💻 Essential Container Commands

bash
# Run a container with common flags
docker run -d \                       # -d = detached (background)
  -p 8080:80 \                        # hostname:container port mapping
  --name my-nginx \                   # friendly name
  --restart unless-stopped \          # auto-restart on crash or reboot
  -e MY_VAR=hello \                  # environment variable injection
  nginx:latest

# List running containers
docker ps

# List ALL containers (running + stopped)
docker ps -a

# Follow container logs in real time (like tail -f)
docker logs -f my-nginx

# ---- Inspection ----
# Get full JSON metadata: IP, mounts, env vars, ports, restart policy
docker inspect my-nginx

# Filter inspect output with Go templates
docker inspect my-nginx --format "{{.NetworkSettings.IPAddress}}"
docker inspect my-nginx --format "{{.State.ExitCode}}"

# Live CPU/memory/network usage
docker stats

# ---- Exec into running container ----
docker exec -it my-nginx /bin/sh      # interactive shell
docker exec my-nginx cat /etc/nginx/nginx.conf   # single command

# Copy files to/from container
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./new-config.conf my-nginx:/etc/nginx/nginx.conf

# ---- Stop / Remove ----
docker stop my-nginx                  # SIGTERM, graceful (10s grace period)
docker kill my-nginx                  # SIGKILL, immediate
docker rm my-nginx                    # remove stopped container
docker rm -f my-nginx                 # force-remove running container

# Remove all stopped containers
docker container prune
💡
Useful inspection patterns

docker inspect <c> | grep -i ip — find container IP.
Exit code meanings: 0 = clean exit, 1 = app error, 137 = OOMKilled (out of memory), 126 = permission denied, 127 = command not found.

🌍 Real-World Use Case

On-call: an alert fires at 2am — a container in staging is restarting in a loop. You run docker ps -a, see it has Exit (137), then docker logs <id> shows an OOM error. docker inspect reveals no memory limit was set. You set --memory 512m and the restarts stop. Five minutes to diagnose and fix.

🧪 Hands-on Exercises

  1. Run nginx in detached mode on port 8080, visit it in a browser, then follow its logs with docker logs -f.
  2. Use docker exec -it to open a shell inside the nginx container — poke around the filesystem.
  3. Use docker inspect to find the container's internal IP address.
  4. Run docker stats while running two containers — observe CPU and memory.
  5. Use docker cp to extract the nginx config file from the container to your host.

🐛 Debugging Scenario

Problem: Container shows Exit (1) in docker ps -a and keeps restarting. You need to diagnose it fast.

bash
# Step 1: identify exit code
docker ps -a                          # look at STATUS column

# Step 2: read the crash output
docker logs <container_id>           # most crashes log the error here

# Step 3: check if OOMKilled
docker inspect <id> | grep -i oom

# Step 4: override entrypoint to get a shell instead of crashing app
docker run -it --entrypoint /bin/sh myapp:latest

# Step 5: if env-var driven crash, inject vars to test
docker run -e DB_URL=postgres://... myapp:latest

🎯 Interview Questions

What is the difference between docker stop and docker kill?

docker stop sends SIGTERM to PID 1 in the container — the app can handle the signal, flush buffers, and close connections gracefully. After the grace period (default 10s), Docker sends SIGKILL. docker kill sends SIGKILL immediately with no grace period. Always use docker stop for clean shutdowns; use docker kill only when the container is frozen or unresponsive.

How do you debug a container that exits immediately on startup?

1. docker ps -a — check exit code (1=app error, 137=OOM, 126=permission denied). 2. docker logs <id> — read stdout/stderr for the error message. 3. Override the entrypoint: docker run -it --entrypoint /bin/sh <image> — get a shell and run the app manually to see the full error. 4. Check required environment variables and config files are present.

Scenario: A production container was changed directly via docker exec. The next deployment reverts those changes. Why?

Containers are ephemeral by design. Any changes made inside a running container exist only in that container's writable layer. When the container is replaced (by a new deployment, a restart, or pod rescheduling in Kubernetes), all runtime changes are lost. Proper fixes must be made to the Dockerfile, rebuilt, and redeployed. Runtime edits are only valid as temporary emergency patches.

📋 Summary