Skip to content
docktionary

Docker

Running containers

A container is a running (or stopped) instance of an image. This is the day-to-day toolkit: start one, look inside it, talk to it, and clean it up.

Starting a container

terminal
# Run in the foreground, see output directly, Ctrl+C to stop
docker run docktionary/app:1.4.0

# -d: detached (background). -p: publish a port. --name: give it a name
docker run -d -p 8080:80 --name app docktionary/app:1.4.0

# Pass environment variables and a restart policy
docker run -d \
  -e NODE_ENV=production \
  -e PORT=80 \
  --restart unless-stopped \
  -p 8080:80 \
  --name app \
  docktionary/app:1.4.0

-p 8080:80 maps port 8080 on the host to port 80 inside the container — the format is always host_port:container_port. For a one-off you don't need to keep around, --rm deletes the container as soon as it exits, instead of leaving a stopped container behind to clean up later.

terminal
docker run --rm -it docktionary/app:1.4.0 sh

Restart policies

--restart tells the daemon what to do when a container's main process exits, or when the daemon itself restarts (a host reboot, a Docker upgrade).

  • no — the default. Never restart automatically.
  • on-failure[:max-retries] — restart only on a non-zero exit code, optionally capped at a number of attempts.
  • always — always restart, including after the daemon restarts — even if you stopped it yourself with docker stop before the daemon went down.
  • unless-stopped — like always, except it respects an explicit docker stop: once you've stopped it on purpose, a daemon restart won't bring it back. This is the one you almost always want for a long-running service.

Graceful shutdown

docker stop sends a stop signal — SIGTERM by default, or whatever the image set with STOPSIGNAL — and waits for the container to exit on its own before forcing it with SIGKILL. --time changes how long it waits.

terminal
docker stop app               # SIGTERM, then SIGKILL after 10s by default
docker stop --time 30 app     # give it 30s to shut down cleanly
docker kill app                # skip straight to SIGKILL

A process that ignores SIGTERM (or isn't PID 1 and never receives it at all — common with shell-form CMD) just gets killed once the grace period runs out, which is why the exec form shown in the CMD reference matters for anything that needs to flush state or close connections before exiting. Either way, the exit code it leaves behind means something specific -- see exit codes.

Looking inside a running container

terminal
# List running containers (add -a to include stopped ones)
docker ps
docker ps -a

# Stream logs; -f follows new output like tail -f
docker logs -f app

# Live resource usage: CPU, memory, network, block I/O
docker stats app

# Everything docker knows about this container as JSON
docker inspect app

# Open an interactive shell inside a running container
docker exec -it app sh

Stopping, restarting, cleaning up

terminal
docker stop app        # sends SIGTERM, then SIGKILL after a grace period
docker start app        # start it again, same container, same writable layer
docker restart app

docker rm app            # remove a stopped container
docker rm -f app          # stop and remove in one step

# Remove every stopped container, unused network, and build cache
docker system prune

# Same, but also remove unused (not just dangling) images
docker system prune -a

Resource limits

Without limits, a single runaway container can starve everything else on the host. Set a hard ceiling on CPU and memory at run time:

terminal
docker run -d \
  --memory=512m \
  --cpus=1.5 \
  -p 8080:80 \
  docktionary/app:1.4.0

Exceed the memory limit and the kernel's OOM killer ends the container's main process; exceed the CPU limit and it's throttled, not killed. Resource limits bound how much a container can take from the host -- see runtime hardening for the flags that bound what it can actually do once it's running.

The container lifecycle

A container moves through a small set of states, visible in the STATUS column of docker ps -a:

  • Created — the container exists but hasn't started (docker create).
  • Running — its main process is active.
  • Paused — frozen with docker pause, no CPU scheduled, resumed with docker unpause.
  • Exited — the main process ended; the writable layer still exists until you docker rm it.