Skip to content
6 min read·Lesson 4 of 10

Running and Managing Containers

Master the docker run command, port publishing, environment variables, restart policies, resource limits, and the container lifecycle.

The previous lesson covered images. This lesson is about running containers — turning images into live processes, configuring them, and managing their lifecycle.

Anatomy of docker run

docker run [OPTIONS] IMAGE [COMMAND] [ARGS...]

A complete example:

docker run -d \
  --name web \
  -p 8080:80 \
  -e NGINX_HOST=example.com \
  --restart unless-stopped \
  nginx:1.27

This: starts in detached mode (-d), names the container web, publishes container port 80 to host port 8080, sets an environment variable, restarts the container automatically unless explicitly stopped, and uses the nginx:1.27 image.

The Most Useful Flags

FlagPurpose
-d / --detachRun in the background
-itInteractive + TTY — for shells and interactive CLIs
--name NAMEAssign a friendly name (otherwise Docker generates one)
-p HOST:CONTAINERPublish a port to the host
-e KEY=VALUESet an environment variable
--env-file PATHLoad env vars from a file
-v HOST:CONTAINERMount a host directory or named volume
--rmAuto-remove the container when it exits
--restart POLICYRestart policy: no, on-failure, always, unless-stopped
--memory 512mMemory limit
--cpus 1.5CPU limit (1.5 cores)
--network NETAttach to a specific network

Interactive Shells

Run a one-shot interactive Ubuntu shell:

docker run --rm -it ubuntu:24.04 bash

The --rm ensures the container is cleaned up when you exit. -it gives you a real terminal.

The Container Lifecycle

  docker run        docker stop / kill         docker start
       │                    │                       │
       ▼                    ▼                       ▼
   created  ─▶  running  ─▶  exited   ─▶  running   ─▶  ...
                                          │
                                          ▼
                                      docker rm  ─▶  gone

Useful management commands:

docker ps                    # running containers
docker ps -a                  # all containers (incl. stopped)
docker stop web               # graceful stop (SIGTERM, then SIGKILL)
docker kill web               # immediate SIGKILL
docker start web              # restart a stopped container
docker restart web            # stop + start
docker rm web                 # remove a stopped container
docker rm -f web              # force-remove a running container
docker logs -f web            # tail logs
docker exec -it web bash      # open a shell inside the container
docker stats                  # live CPU/mem usage of running containers
docker inspect web            # full JSON metadata

Publishing Ports

By default, a container's network ports are private to the container. -p opens a hole in the host:

docker run -p 8080:80 nginx          # host:8080 → container:80
docker run -p 127.0.0.1:8080:80 nginx  # bind only to loopback
docker run -P nginx                    # publish all EXPOSEd ports to random hosts

Environment Variables and Secrets

Twelve-factor apps configure themselves through environment variables, which is exactly how container images expect to be configured:

docker run -e DATABASE_URL=postgres://... -e LOG_LEVEL=info myapp
docker run --env-file .env myapp

Never bake secrets into images. Use environment variables, secret managers (AWS Secrets Manager, Azure Key Vault), or Docker secrets / Kubernetes Secrets. Anything in an image is visible to anyone who can pull it.

Restart Policies

PolicyBehaviour
no (default)Don't restart
on-failure[:N]Restart only on non-zero exit, optionally up to N times
alwaysRestart on any exit, including manual docker stop after daemon reboot
unless-stoppedRestart unless you explicitly stopped it (the production default)

Resource Limits

By default, a container can use all the host's CPU and memory — a runaway container can take down the host. In production, always set limits:

docker run --memory 512m --memory-swap 1g --cpus 1.5 myapp

Kubernetes makes these limits explicit (requests and limits in pod specs) — but the same kernel-level cgroups enforce them.

Key Takeaways

  • docker run starts a new container; common flags: -d (detached), -p (publish ports), -e (env), --name, --rm.
  • Containers have a lifecycle: created → running → paused/stopped → removed.
  • -p HOST:CONTAINER publishes a container port to the host so external traffic can reach it.
  • Use -e KEY=VALUE or --env-file to inject configuration; never bake secrets into images.
  • --restart unless-stopped keeps a container running across daemon restarts in production.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →