Skip to main content

Docker Fundamentals

Master the core concepts of Docker containerization and understand how containers revolutionized software deployment.

What is Docker?

Docker is a platform for developing, shipping, and running applications in containers. Containers package your application with all its dependencies, ensuring it runs consistently across different environments.

Lightweight

Containers share the host OS kernel, using MBs instead of GBs

Portable

Run anywhere - laptop, server, cloud

Fast

Start in seconds, not minutes

Isolated

Each container runs independently

Images vs Containers

Understanding the difference is crucial:

Docker Images

  • Blueprint for containers (like a class in OOP)
  • Read-only template
  • Contains application code, runtime, libraries, dependencies
  • Stored in registries (Docker Hub, private registries)
  • Built from Dockerfile

Docker Containers

  • Running instance of an image (like an object in OOP)
  • Writable layer on top of image
  • Isolated process with own filesystem, network, process tree
  • Can be started, stopped, deleted
  • Multiple containers from same image
# Analogy
Image = Recipe
Container = Cake baked from recipe

# You can bake many cakes (containers) from one recipe (image)

Docker Architecture

Docker uses a client-server architecture:
┌─────────────┐         ┌──────────────────┐         ┌─────────────┐
│   Docker    │  REST   │  Docker Daemon   │         │   Docker    │
│   Client    │────────▶│    (dockerd)     │◀────────│  Registry   │
│   (CLI)     │   API   │                  │  Pull/  │ (Docker Hub)│
└─────────────┘         └──────────────────┘  Push   └─────────────┘

                               │ Manages

                        ┌──────────────┐
                        │  Containers  │
                        │    Images    │
                        │   Networks   │
                        │   Volumes    │
                        └──────────────┘

Components

Docker Client (docker):
  • Command-line interface
  • Sends commands to Docker daemon
  • Can communicate with remote daemons
Docker Daemon (dockerd):
  • Background service
  • Builds, runs, manages containers
  • Listens for Docker API requests
Docker Registry:
  • Stores Docker images
  • Docker Hub (public)
  • Private registries (AWS ECR, Google GCR, Azure ACR)

Installing Docker

# Download Docker Desktop from docker.com
# Or use winget
winget install Docker.DockerDesktop

# Verify installation
docker --version
docker run hello-world

Essential Docker Commands

Working with Images

# Search for images
docker search nginx

# Pull image from Docker Hub
docker pull nginx
docker pull nginx:1.21  # Specific version

# List local images
docker images
docker image ls

# Inspect image
docker inspect nginx

# Remove image
docker rmi nginx
docker image rm nginx

# Remove unused images
docker image prune
docker image prune -a  # Remove all unused

Working with Containers

# Run container
docker run nginx
docker run -d nginx  # Detached mode (background)
docker run -d --name my-nginx nginx  # With name
docker run -d -p 8080:80 nginx  # Port mapping (host:container)

# List containers
docker ps  # Running only
docker ps -a  # All (including stopped)

# Stop container
docker stop my-nginx
docker stop $(docker ps -q)  # Stop all running

# Start stopped container
docker start my-nginx

# Restart container
docker restart my-nginx

# Remove container
docker rm my-nginx
docker rm -f my-nginx  # Force remove (even if running)

# Remove all stopped containers
docker container prune

Container Interaction

# View logs
docker logs my-nginx
docker logs -f my-nginx  # Follow (live)
docker logs --tail 100 my-nginx  # Last 100 lines

# Execute command in running container
docker exec my-nginx ls /usr/share/nginx/html
docker exec -it my-nginx bash  # Interactive shell

# Copy files
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./index.html my-nginx:/usr/share/nginx/html/

# View container stats
docker stats
docker stats my-nginx

# Inspect container
docker inspect my-nginx

Practical Examples

Example 1: Running Nginx Web Server

# Pull and run nginx
docker run -d \
  --name web-server \
  -p 8080:80 \
  nginx:alpine

# Verify it's running
curl http://localhost:8080

# View logs
docker logs web-server

# Stop and remove
docker stop web-server
docker rm web-server

Example 2: Running a Database

# Run PostgreSQL
docker run -d \
  --name postgres-db \
  -e POSTGRES_PASSWORD=mysecret \
  -e POSTGRES_DB=myapp \
  -p 5432:5432 \
  postgres:14

# Connect to database
docker exec -it postgres-db psql -U postgres -d myapp

# Stop and remove (data is lost!)
docker stop postgres-db
docker rm postgres-db

Example 3: Interactive Container

# Run Ubuntu container interactively
docker run -it ubuntu:22.04 bash

# Inside container:
apt update
apt install curl
curl https://example.com
exit

# Container stops when you exit

Container Lifecycle

┌─────────┐
│ Created │  docker create
└────┬────┘


┌─────────┐
│ Running │  docker start / docker run
└────┬────┘

     ├──▶ Paused   (docker pause)
     │      │
     │      └──▶ Running (docker unpause)


┌─────────┐
│ Stopped │  docker stop
└────┬────┘


┌─────────┐
│ Removed │  docker rm
└─────────┘

Common Flags and Options

# -d, --detach          Run in background
# -p, --publish         Port mapping (host:container)
# --name               Assign name to container
# -e, --env            Set environment variables
# -v, --volume         Mount volume
# --rm                 Remove container when stopped
# -it                  Interactive terminal
# --network            Connect to network
# --restart            Restart policy

# Example with multiple flags
docker run -d \
  --name my-app \
  -p 3000:3000 \
  -e NODE_ENV=production \
  -v $(pwd):/app \
  --restart unless-stopped \
  node:18

Environment Variables

# Set single variable
docker run -e DATABASE_URL=postgres://localhost:5432/db myapp

# Set multiple variables
docker run \
  -e NODE_ENV=production \
  -e PORT=3000 \
  -e DATABASE_URL=postgres://db:5432/mydb \
  myapp

# From file
docker run --env-file .env myapp

Docker System Commands

# View Docker disk usage
docker system df

# Clean up everything
docker system prune  # Remove stopped containers, unused networks, dangling images
docker system prune -a  # Also remove unused images
docker system prune -a --volumes  # Also remove unused volumes

# View Docker info
docker info

# View Docker version
docker version

Best Practices

# Bad
docker pull nginx

# Good
docker pull nginx:1.21-alpine
Avoid latest tag in production - it’s unpredictable.
# Bad
docker run -d nginx

# Good
docker run -d --name web-server nginx
Makes management easier.
# Remove stopped containers
docker container prune

# Remove unused images
docker image prune

# Remove everything unused
docker system prune -a
# Container auto-removes when stopped
docker run --rm -it ubuntu bash

Troubleshooting

Container Won’t Start

# Check logs
docker logs container-name

# Inspect container
docker inspect container-name

# Check if port is already in use
netstat -an | grep 8080  # Linux/Mac
netstat -an | findstr 8080  # Windows

Permission Denied

# Linux: Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in

# Or run with sudo
sudo docker ps

Container Keeps Restarting

# Check logs
docker logs container-name

# Run without restart policy
docker run -d --name test nginx
# Debug the issue

Key Takeaways

  • Docker containers are lightweight, portable, and fast
  • Images are blueprints, containers are running instances
  • Use docker run to create and start containers
  • Use docker ps to list containers
  • Use docker logs to debug
  • Clean up regularly with docker system prune

Container Internals (Critical for Interviews!)

Understanding what makes containers work under the hood is essential for senior roles.

Linux Namespaces

Namespaces provide isolation. Each container gets its own view of:
NamespaceIsolates
PIDProcess IDs (container sees itself as PID 1)
NETNetwork stack (own IP, ports, routing)
MNTFilesystem mounts
UTSHostname and domain name
IPCInter-process communication
USERUser and group IDs

Control Groups (cgroups)

Cgroups provide resource limiting:
# Limit memory to 512MB
docker run -m 512m nginx

# Limit CPU to 0.5 cores
docker run --cpus 0.5 nginx

# cgroups enforce these limits at kernel level

Union Filesystem (OverlayFS)

Docker images use layered filesystems:
┌─────────────────────────┐
│   Container Layer (RW)  │  ← Writable layer
├─────────────────────────┤
│   Application Layer     │  ← COPY . .
├─────────────────────────┤
│   Dependencies Layer    │  ← npm install
├─────────────────────────┤
│   Base Image Layer      │  ← FROM node:18
└─────────────────────────┘
Interview Insight: Containers are NOT lightweight VMs. They’re isolated processes sharing the host kernel, using namespaces for isolation and cgroups for resource limits.

OCI (Open Container Initiative)

The industry standard for container formats and runtimes.

OCI Standards

StandardDescription
Image SpecHow container images are built and distributed
Runtime SpecHow containers are executed
Distribution SpecHow images are pushed/pulled from registries

Container Runtimes

RuntimeDescriptionUse Case
containerdIndustry standard, used by Docker/K8sProduction
CRI-OLightweight, Kubernetes-nativeKubernetes
runcLow-level runtime (OCI reference)Building runtimes
gVisorSandboxed (user-space kernel)Security-critical
Kata ContainersVM-based isolationMulti-tenancy

Docker Security Best Practices

1. Run as Non-Root

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

2. Read-Only Filesystem

docker run --read-only nginx

3. Drop Capabilities

# Run with minimal capabilities
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

4. Security Scanning

# Scan image for vulnerabilities
docker scout cves nginx:latest

# Using Trivy
trivy image nginx:latest

Interview Questions & Answers

AspectContainerVirtual Machine
IsolationProcess-level (namespaces)Hardware-level (hypervisor)
KernelShares host kernelHas own kernel
SizeMBsGBs
StartupSecondsMinutes
Resource UsageLow overheadHigh overhead
SecurityWeaker isolationStronger isolation
Namespaces: Provide isolation (what a container can see)
  • PID namespace: Own process tree
  • NET namespace: Own network stack
  • MNT namespace: Own filesystem view
cgroups: Provide resource limits (what a container can use)
  • CPU limits
  • Memory limits
  • I/O bandwidth
  1. Docker CLI sends request to Docker daemon
  2. Daemon checks if image exists locally
  3. If not, pulls from registry (Docker Hub)
  4. Creates a new container from image layers
  5. Allocates a read-write layer on top
  6. Creates network interface and assigns IP
  7. Starts the container process with namespaces and cgroups
  8. Executes the CMD/ENTRYPOINT
InstructionBehaviorOverridable
CMDDefault command/argumentsYes, with docker run args
ENTRYPOINTMain executableOnly with —entrypoint
Best Practice: Use ENTRYPOINT for the executable, CMD for default arguments:
ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8080"]
  1. Check logs: docker logs container_name
  2. Inspect: docker inspect container_name
  3. Run interactively: docker run -it image sh
  4. Override entrypoint: docker run --entrypoint sh image
  5. Check events: docker events
  6. Resource issues: docker stats
BuildKit is the modern builder for Docker images:
  • Parallel builds: Build independent stages concurrently
  • Better caching: Cache mounts for package managers
  • Secret mounting: Don’t bake secrets into layers
  • SSH forwarding: Clone private repos during build
Enable: DOCKER_BUILDKIT=1 docker build .

Common Pitfalls

1. Using latest Tag: Unpredictable. Always use specific version tags.2. Running as Root: Security risk. Create and use a non-root user.3. Large Images: Slow pulls and more attack surface. Use Alpine or distroless.4. Not Cleaning Up: Disk fills up fast. Run docker system prune regularly.5. Storing Data in Containers: Data is lost when container dies. Use volumes!6. Ignoring Resource Limits: Containers can consume all host resources without limits.

Next: Building Docker Images →