Running Containers
Running Containers
Knowing how to pull an image is table stakes. The real skill is knowing exactly how to launch, inspect, control, and debug a container in production — and why each flag exists. At big-tech scale, a misunderstood flag means a runaway process, a secret leaked into logs, or a container that silently exits and never restarts. This lesson covers the full container lifecycle through docker run and its companions.
The Full docker run Anatomy
Every invocation of docker run creates a new container from an image, runs a single process (PID 1), and exits when that process exits. The syntax is:
The most important flags to internalize:
-d/--detach— Run in the background; print container ID and return to shell. This is the default for long-running services.-it— Allocate a pseudo-TTY (-t) and keep STDIN open (-i). Use together for interactive shells. Never combine with-dfor services.--name— Assign a deterministic name. Without it, Docker generates a random adjective-noun pair — unmanageable at scale.--rm— Remove the container automatically when it exits. Critical for one-off debugging containers and CI runners to prevent disk exhaustion.-p HOST:CONTAINER— Publish a port.-p 8080:80binds host port 8080 to container port 80.-e KEY=VALUE— Inject an environment variable. The preferred way to pass configuration; never bake secrets into images.--env-file FILE— Bulk-inject env vars from a file. Use for long config lists or secrets in CI.--restart— Restart policy:no(default),always,on-failure[:N],unless-stopped. Production services useunless-stoppedso they survive host reboots but can be deliberately stopped.--memory/--cpus— Hard resource limits. Without them, one runaway container can starve neighbors on the same host.--user— Override the UID/GID at runtime. Use to avoid running as root inside the container.--read-only— Mount the container filesystem as read-only. Forces the process to write only to explicitly mounted volumes — a defense-in-depth security control.
@sha256:abc123…) in production manifests. latest is a mutable pointer that changes silently and makes rollbacks impossible.
Container Lifecycle
A container transitions through well-defined states. Understanding these is essential for writing health checks and restart logic.
Key lifecycle commands:
docker stop vs docker kill: Always prefer stop. It sends SIGTERM first, giving your application time to flush buffers, close database connections, and finish in-flight requests. kill sends SIGKILL immediately and can corrupt state. The 10-second default timeout is often too short for databases — tune it per service with --time.
Streaming Logs
The docker logs command reads from the container's configured log driver. The default driver (json-file) writes stdout/stderr to a JSON file on the host. In production, you switch to a driver that ships logs to a centralized system (Loki, Splunk, CloudWatch), but docker logs remains invaluable for local debugging.
Executing Commands in a Running Container
docker exec spawns a new process inside an already-running container's namespaces. It does not touch PID 1. This is the correct tool for live debugging — not restarting the container.
curl, strace, or tcpdump into a running production container significantly expands the attack surface. Pre-plan your observability strategy before an incident occurs.
Inspecting Container State
docker inspect returns the full JSON representation of a container or image — mounts, network config, environment variables, resource limits, health check status, exit codes, and more. It is the authoritative source of truth about a container's live configuration.
docker ps to confirm state, (2) docker logs to read recent output, (3) docker inspect to verify config (env vars, mounts, restart count), (4) docker stats to rule out resource exhaustion, (5) docker exec for live investigation if the container is still running.
Copying Files to and from Containers
Occasionally you need to pull a config file or a generated artifact out of a running container for inspection, or push a temporary file in for testing. docker cp handles this without a volume mount.
Putting It Together: A Production-Hardened Run Command
Here is what a security-hardened, production-ready docker run for a web API looks like — every flag is intentional:
This pattern — minimal Linux capabilities, read-only filesystem, explicit resource ceilings, loopback-only port binding — is the baseline that security-conscious engineering organizations apply to every production container before they even consider the orchestrator (Kubernetes) layer on top.