Skip to main content

Running Containers

Every container starts with docker run, but the flags you choose determine how it behaves. This lesson focuses on the two fundamental modes -- interactive and detached -- and the options you will use most often in practice.

Interactive vs Detached

flowchart LR
subgraph interactive["Interactive (-it)"]
A["Terminal attached"] --> B["You type commands"]
B --> C["Exit ends container"]
end

subgraph detached["Detached (-d)"]
D["Runs in background"] --> E["Logs to docker logs"]
E --> F["Stays running after terminal closes"]
end

style interactive fill:#e3f2fd,stroke:#1565c0
style detached fill:#e8f5e9,stroke:#2e7d32
ModeFlagsUse Case
Interactive-itDebugging, exploring images, one-off scripts
Detached-dServices, databases, web servers

Interactive Mode

Interactive mode attaches your terminal to the container. You get a shell prompt and can type commands directly:

# Start an Ubuntu container and drop into bash
docker run --rm -it ubuntu:22.04 bash
  • -i keeps STDIN open so you can type input
  • -t allocates a pseudo-TTY so you get a proper prompt
  • --rm removes the container automatically when you exit

Practical Examples

# Explore an image's filesystem
docker run --rm -it alpine:3.19 sh

# Run a Python script interactively
docker run --rm -it python:3.12 python3

# Test network tools inside a container
docker run --rm -it nicolaka/netshoot bash

# Start a Node.js REPL
docker run --rm -it node:20-alpine node
tip

Use --rm with interactive containers. Without it, exited containers accumulate and waste disk space. Check with docker ps -a.

Detached Mode

Detached mode runs the container in the background. You get the container ID back immediately:

docker run -d --name web nginx:alpine
# Returns: a1b2c3d4e5f6...

The container keeps running after your terminal session ends. Use docker logs and docker exec to interact with it.

Practical Examples

# Run a web server on port 8080
docker run -d --name web -p 8080:80 nginx:alpine

# Run a PostgreSQL database
docker run -d \
--name db \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
postgres:16

# Run Redis as a cache
docker run -d --name cache -p 6379:6379 redis:7-alpine

Essential Run Options

OptionPurposeExample
--nameAssign a memorable name--name my-api
-p / --publishMap host port to container port-p 8080:80
-v / --volumeMount storage-v data:/app/data
-e / --envSet environment variable-e NODE_ENV=production
--rmAuto-remove on exit--rm
--restartRestart policy--restart unless-stopped
-w / --workdirSet working directory-w /app
--hostnameSet container hostname--hostname api-server
--networkConnect to a network--network my-net
--read-onlyMake filesystem read-only--read-only

Combining Options: Real-World Patterns

Development Web Server

docker run -d \
--name dev-server \
--rm \
-p 3000:3000 \
-v "$(pwd)":/app \
-w /app \
node:20-alpine \
npm run dev

Production API Server

docker run -d \
--name api \
-p 8080:8080 \
--restart unless-stopped \
--memory=512m \
--cpus=1.0 \
-e NODE_ENV=production \
my-api:1.0.0

One-Off Job

docker run --rm \
-v "$(pwd)/output":/output \
my-report-generator:latest \
--format=pdf --output=/output/report.pdf

Container Naming Conventions

ConventionExampleWhen to Use
Service nameweb, api, dbSingle-instance services
Project-servicemyapp-web, myapp-dbMultiple projects on one host
Service-environmentapi-staging, api-prodMultiple environments
warning

Avoid using default random names (like quirky_einstein) in any script or production setup. Random names make debugging and automation impossible.

Port Mapping in Detail

# Map host port 8080 to container port 80
docker run -d -p 8080:80 nginx:alpine

# Bind to localhost only (not exposed to network)
docker run -d -p 127.0.0.1:8080:80 nginx:alpine

# Map multiple ports
docker run -d -p 8080:80 -p 8443:443 nginx:alpine

# Let Docker assign a random host port
docker run -d -p 80 nginx:alpine
docker port <container> # See assigned port
SyntaxMeaning
-p 8080:80Host 8080 → Container 80 (all interfaces)
-p 127.0.0.1:8080:80Host 8080 → Container 80 (localhost only)
-p 80Random host port → Container 80
-p 8080:80/udpUDP port mapping

Managing Running Containers

CommandWhat It Does
docker psList running containers
docker ps -aList all containers (including stopped)
docker stop <name>Gracefully stop a container
docker start <name>Start a stopped container
docker restart <name>Stop and start a container
docker rm <name>Remove a stopped container
docker rm -f <name>Force-remove (even if running)

Bulk Operations

# Stop all running containers
docker stop $(docker ps -q)

# Remove all stopped containers
docker container prune

# Remove all containers (running and stopped)
docker rm -f $(docker ps -aq)
danger

docker rm -f $(docker ps -aq) removes every container on the host, including databases with data. Use with extreme caution.

Key Takeaways

  • Interactive mode (-it) is for exploration and debugging; detached mode (-d) is for services.
  • Always use --name so you can reference containers predictably.
  • Use --rm for throwaway containers to prevent accumulation.
  • Bind ports to 127.0.0.1 when the service should not be exposed to the network.
  • Combine --restart unless-stopped with resource limits for production deployments.

What's Next

  • Continue to Container Interaction to learn how to execute commands, attach, and copy files in running containers.