Docker Basics

Docker Hub and Registries

Docker Hub (hub.docker.com) hosts pre-built container images. When you run:

docker run python:3.11-slim

Docker pulls the image from Docker Hub if not present locally. The format is:

[REGISTRY/]USERNAME/IMAGE[:TAG]
  • No registry specified → defaults to Docker Hub
  • No username → official images (python, ubuntu, nginx)
  • No tag → defaults to latest

Common registries:

  • docker.io - Docker Hub (default)
  • ghcr.io - GitHub Container Registry
  • gcr.io - Google Container Registry
  • localhost:5000 - Local registry

Building Images

A Dockerfile defines the build process:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]

Build with:

# Basic build
docker build -t myapp .

# With specific tag
docker build -t myapp:v1.0 .

# With build arguments
docker build --build-arg VERSION=1.0 -t myapp .

# From specific Dockerfile
docker build -f Dockerfile.dev -t myapp:dev .

The -t flag tags the image. Without it, you get an unnamed image with only an ID.

Running Containers

Basic run patterns:

# Run interactively with terminal
docker run -it ubuntu bash

# Run in background (detached)
docker run -d nginx

# Remove container after exit
docker run --rm python:3.11 python -c "print('Hello')"

# Name the container
docker run --name webserver -d nginx

Container lifecycle:

  1. docker run creates and starts a new container
  2. Container runs until main process exits
  3. Container remains in stopped state unless --rm used

Port Mapping

Expose container ports to host:

# Map port 80 in container to 8080 on host
docker run -p 8080:80 nginx

# Map to specific interface
docker run -p 127.0.0.1:8080:80 nginx

# Map random host port
docker run -P nginx  # Maps all exposed ports

# Multiple ports
docker run -p 8080:80 -p 8443:443 nginx

Format: -p [HOST_IP:]HOST_PORT:CONTAINER_PORT

Volume Mounts

Share data between host and container:

# Bind mount (absolute path required)
docker run -v /path/on/host:/path/in/container nginx

# Bind mount with pwd
docker run -v $(pwd)/data:/app/data python:3.11

# Read-only mount
docker run -v $(pwd)/config:/etc/config:ro nginx

# Named volume (Docker-managed)
docker volume create mydata
docker run -v mydata:/data postgres

# Anonymous volume
docker run -v /data postgres  # Creates unnamed volume

Bind mounts vs Volumes:

  • Bind mounts: Direct host filesystem access, use absolute paths
  • Named volumes: Docker-managed, portable, better for databases
  • Anonymous volumes: Temporary, deleted with container

Environment Variables

Pass configuration to containers:

# Single variable
docker run -e DATABASE_URL=postgres://localhost/db postgres

# Multiple variables
docker run -e USER=admin -e PASSWORD=secret nginx

# From file
docker run --env-file .env python:3.11

# From host environment
docker run -e HOME myapp  # Passes $HOME from host

Environment file format:

# .env file
DATABASE_URL=postgres://localhost/db
API_KEY=abc123
DEBUG=true

Container Management

Control running containers:

# List running containers
docker ps

# List all containers
docker ps -a

# Stop container (SIGTERM, then SIGKILL after 10s)
docker stop container_name

# Kill immediately (SIGKILL)
docker kill container_name

# Restart container
docker restart container_name

# Remove stopped container
docker rm container_name

# Remove running container
docker rm -f container_name

Executing Commands

Run commands in existing containers:

# Execute command in running container
docker exec container_name ls -la

# Interactive shell in running container
docker exec -it container_name bash

# As different user
docker exec -u www-data container_name whoami

# With environment variable
docker exec -e DEBUG=true container_name python script.py

exec vs run:

  • run creates NEW container
  • exec runs in EXISTING container

Names vs IDs vs Labels

Three ways to identify containers:

# By name (user-defined)
docker run --name myapp nginx
docker stop myapp

# By ID (auto-generated)
docker ps -q  # Show only IDs
docker stop a1b2c3d4

# By label (metadata)
docker run --label env=prod --label team=backend nginx
docker ps --filter label=env=prod

Names must be unique. IDs are unique hashes. Labels are key-value metadata for organization.


Command Reference

Quick lookup for common Docker commands:

docker build

Build image from Dockerfile:

docker build [OPTIONS] PATH

Options:
  -t, --tag        Name and tag (name:tag)
  -f, --file       Dockerfile path
  --build-arg      Set build-time variables
  --no-cache       Build without cache
  --target         Build specific stage

Examples:
  docker build -t myapp:latest .
  docker build -f Dockerfile.dev -t myapp:dev .
  docker build --build-arg VERSION=1.0 -t myapp:v1 .

docker run

Create and start container:

docker run [OPTIONS] IMAGE [COMMAND]

Options:
  -d, --detach     Run in background
  -it              Interactive with TTY
  --rm             Remove after exit
  --name           Container name
  -p, --publish    Port mapping (host:container)
  -v, --volume     Volume mount
  -e, --env        Environment variable
  --network        Connect to network
  -u, --user       Username or UID

Examples:
  docker run -d --name web -p 8080:80 nginx
  docker run -it --rm ubuntu bash
  docker run -v $(pwd):/app -e DEBUG=true myapp

docker ps

List containers:

docker ps [OPTIONS]

Options:
  -a, --all        Show all (including stopped)
  -q, --quiet      Only display IDs
  -f, --filter     Filter output
  --format         Format output

Examples:
  docker ps                          # Running containers
  docker ps -a                       # All containers
  docker ps -q                       # Only IDs
  docker ps --filter status=exited   # Stopped containers
  docker ps --format "table {{.Names}}\t{{.Status}}"

docker exec

Execute in running container:

docker exec [OPTIONS] CONTAINER COMMAND

Options:
  -i, --interactive    Keep STDIN open
  -t, --tty           Allocate pseudo-TTY
  -e, --env           Set environment variable
  -u, --user          Username or UID
  -w, --workdir       Working directory

Examples:
  docker exec myapp ls -la
  docker exec -it myapp bash
  docker exec -u root myapp apt update
  docker exec -e VAR=value myapp env

docker stop/kill

Stop containers:

docker stop [OPTIONS] CONTAINER    # Graceful (SIGTERM)
docker kill [OPTIONS] CONTAINER    # Force (SIGKILL)

Options:
  -t, --time       Seconds to wait before killing (stop only)

Examples:
  docker stop myapp              # 10 second grace period
  docker stop -t 30 myapp        # 30 second grace period
  docker kill myapp              # Immediate termination
  docker stop $(docker ps -q)    # Stop all running

docker rm/rmi

Remove containers and images:

docker rm [OPTIONS] CONTAINER      # Remove container
docker rmi [OPTIONS] IMAGE          # Remove image

Options:
  -f, --force      Force removal
  -v, --volumes    Remove associated volumes

Examples:
  docker rm myapp                    # Remove stopped container
  docker rm -f myapp                 # Force remove running
  docker rm $(docker ps -aq)         # Remove all containers
  docker rmi myimage:tag              # Remove image
  docker rmi $(docker images -q)     # Remove all images

docker logs

View container logs:

docker logs [OPTIONS] CONTAINER

Options:
  -f, --follow     Follow log output
  -t, --timestamps Show timestamps
  --tail           Number of lines from end
  --since          Show logs since timestamp

Examples:
  docker logs myapp
  docker logs -f myapp              # Follow live
  docker logs --tail 50 myapp       # Last 50 lines
  docker logs --since 10m myapp     # Last 10 minutes

docker cp

Copy files between container and host:

docker cp [OPTIONS] SRC DEST

Examples:
  docker cp myapp:/app/config.json ./config.json    # Container to host
  docker cp ./data.csv myapp:/app/data.csv          # Host to container
  docker cp myapp:/logs ./backup/                   # Copy directory

docker inspect

View detailed container/image info:

docker inspect [OPTIONS] NAME|ID

Examples:
  docker inspect myapp                              # Full JSON output
  docker inspect -f '{{.State.Status}}' myapp       # Specific field
  docker inspect -f '{{.NetworkSettings.IPAddress}}' myapp
  docker inspect -f '{{json .Mounts}}' myapp | jq   # With jq

docker volume

Manage volumes:

docker volume [COMMAND]

Commands:
  create    Create a volume
  ls        List volumes
  rm        Remove volumes
  inspect   Display volume details
  prune     Remove all unused volumes

Examples:
  docker volume create mydata
  docker volume ls
  docker volume rm mydata
  docker volume prune -f    # Remove unused