You can start and stop a container - now it is time to truly manage them. This lesson covers the complete container lifecycle, interactive containers, restart policies, resource limits, and the inspection tools you will reach for when something goes wrong.
A container moves through a small set of states: created, running, paused, stopped (exited), and finally removed. The commands map directly onto these transitions:
docker create --name app nginx # created, but not started
docker start app # running
docker pause app # paused (processes frozen)
docker unpause app # running again
docker stop app # graceful stop (SIGTERM, then SIGKILL)
docker restart app # stop + start in one step
docker rm app # gonedocker run is simply create plus start in one command. docker stop sends SIGTERM and waits ten seconds before forcing SIGKILL; use docker kill only when a container refuses to die.
For experimentation, run a container with an interactive terminal:
docker run -it --rm ubuntu bash-i keeps STDIN open, -t allocates a terminal - together they give you a usable shell.--rm deletes the container automatically when you exit, keeping your system clean.This pattern is perfect for testing commands in a throwaway Linux environment. Need Python for five minutes? docker run -it --rm python:3.12 python drops you straight into a REPL.
docker exec runs an additional process inside a container that is already running:
docker exec -it app sh # open a shell
docker exec app ls /usr/share/nginx/html # run a one-off commandThis is the standard way to debug: open a shell, check config files, test network reachability from inside the container.
Three commands answer most "what is happening?" questions:
docker logs -f --tail 100 app # follow the last 100 log lines
docker stats # live CPU, memory, and network usage
docker inspect app # full JSON: config, network, mountsdocker logs shows everything the main process wrote to stdout and stderr - which is why containerized apps log to the console instead of files. docker inspect combined with a format string extracts specific fields:
docker inspect -f "{{.NetworkSettings.IPAddress}}" appBy default a crashed container stays down. Restart policies make containers self-healing:
docker run -d --restart unless-stopped nginxno - never restart (default)on-failure - restart only when the app exits with an error codealways - restart on any exit, and on daemon startupunless-stopped - like always, but respects a manual docker stopFor anything meant to run long-term, unless-stopped is the sensible choice.
A runaway container can starve the whole host. Cap its resources at run time:
docker run -d --memory 512m --cpus 1.5 nginxThis container may use at most 512 MB of RAM and one and a half CPU cores. Setting limits is essential on shared servers.
Over time, stopped containers and unused images accumulate. Clean house with:
docker container prune # remove all stopped containers
docker system prune # also remove dangling images and networks
docker system df # see what is using disk space-it --rm gives you disposable interactive environments for quick experiments.docker logs, docker stats, and docker inspect are your primary debugging tools.--restart unless-stopped for long-running services.Next up: Writing a Dockerfile, where you stop consuming other people's images and start building your own.