Docker for Beginners: Complete Guide (2026)
Docker for Beginners: Complete Guide (2026)
Last Updated: March 2026 | 18 min read | For DevOps Beginners & Developers
If you're learning DevOps in 2026, Docker is non-negotiable. Every modern application runs in containers. Every CI/CD pipeline builds Docker images. Every Kubernetes cluster runs Docker containers. Yet most beginners find Docker confusing at first — what exactly is a container? How is it different from a virtual machine? How do you actually use it?
This guide covers everything you need to know about Docker — from installing it to deploying real applications — with hands-on examples you can follow along with right now.
Table of Contents
- What is Docker?
- Containers vs Virtual Machines
- Key Docker Concepts
- Installing Docker
- Essential Docker Commands
- Writing Your First Dockerfile
- Docker Volumes — Persisting Data
- Docker Networking
- Docker Compose — Multi-Container Apps
- Docker in CI/CD Pipelines
- Docker Best Practices
- Common Docker Interview Questions
- Quick Reference Cheat Sheet
1. What is Docker?
Docker is an open-source platform that allows you to package applications and their dependencies into portable, lightweight units called containers. These containers can run consistently on any machine — your laptop, a colleague's computer, a staging server, or a production cloud instance — without the dreaded "it works on my machine" problem.
Before Docker, deploying applications was painful:
- Different environments had different software versions
- "Works on my machine" was a constant problem
- Setting up a new server took hours or days
- Scaling applications required provisioning entire new servers
Docker solves all of this by bundling your application code, runtime, libraries, and configuration into a single container image that runs identically everywhere.
Simple analogy: Think of a Docker container like a shipping container. Before standardised shipping containers, every ship, truck, and warehouse had to be custom-built for different cargo. Standardised containers changed everything — the same container moves by ship, truck, and train without repacking. Docker does the same for software.
2. Containers vs Virtual Machines
This is one of the most common interview questions — and one of the most misunderstood concepts for beginners.
Virtual Machines (VMs)
A VM includes a full operating system on top of a hypervisor. Each VM has its own kernel, OS libraries, and application. They are heavy — typically 10–20GB each — and take minutes to start.
┌─────────────────────────────────┐
│ Your Application │
├─────────────────────────────────┤
│ Guest OS (Full) │
├─────────────────────────────────┤
│ Hypervisor │
├─────────────────────────────────┤
│ Host Operating System │
├─────────────────────────────────┤
│ Hardware │
└─────────────────────────────────┘Docker Containers
Containers share the host OS kernel. They only package the application and its dependencies — not a full OS. They are lightweight (typically 100MB–500MB), start in seconds, and run in isolation.
┌──────────┐ ┌──────────┐ ┌──────────┐
│ App A │ │ App B │ │ App C │
│ + Deps │ │ + Deps │ │ + Deps │
├──────────┴─┴──────────┴─┴──────────┤
│ Docker Engine │
├────────────────────────────────────┤
│ Host Operating System │
├────────────────────────────────────┤
│ Hardware │
└────────────────────────────────────┘Comparison Table
| Feature | Virtual Machine | Docker Container |
|---|---|---|
| Size | 10–20 GB | 100MB–500MB |
| Startup time | Minutes | Seconds |
| OS | Full guest OS | Shares host OS kernel |
| Isolation | Strong | Good (process-level) |
| Performance | Slower (overhead) | Near-native |
| Portability | Limited | Runs anywhere |
| Use case | Full OS isolation | App packaging & scaling |
3. Key Docker Concepts
Before jumping into commands, understand these five core concepts:
Docker Image
A read-only template used to create containers. Think of it as a blueprint or a class in programming. Images are built from a Dockerfile and stored in a registry.
Docker Container
A running instance of an image. Think of it as an object created from a class. You can run multiple containers from the same image simultaneously.
Dockerfile
A text file with instructions for building a Docker image — what base image to use, what files to copy, what commands to run.
Docker Registry
A storage system for Docker images. Docker Hub is the public registry. AWS ECR, Azure ACR, and Google GCR are private enterprise registries.
Docker Engine
The runtime that runs containers on your machine. It includes the Docker daemon (background service) and the Docker CLI (command line tool).
Dockerfile → docker build → Image → docker run → Container
↓
Docker Registry
(Docker Hub / ECR / ACR)4. Installing Docker
On Ubuntu/Debian Linux
# Update package index
$ sudo apt update
# Install required packages
$ sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# Add Docker's official GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Add Docker repository
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Install Docker
$ sudo apt update
$ sudo apt install -y docker-ce
# Start Docker service
$ sudo systemctl start docker
$ sudo systemctl enable docker
# Run Docker without sudo
$ sudo usermod -aG docker $USER
$ newgrp docker
# Verify installation
$ docker --version
Docker version 26.0.0, build abc1234On Windows / Mac
Download and install Docker Desktop from docker.com/products/docker-desktop. It includes everything you need including the Docker CLI and a GUI dashboard.
Verify Installation
# Check Docker version
$ docker --version
# Run your first container
$ docker run hello-world
# Output:
Hello from Docker!
This message shows that your installation appears to be working correctly.5. Essential Docker Commands
Working with Images
# Pull an image from Docker Hub
$ docker pull nginx
# Pull a specific version (tag)
$ docker pull nginx:1.25
# List all local images
$ docker images
# Remove an image
$ docker rmi nginx
# Remove all unused images
$ docker image prune -a
# Search for images on Docker Hub
$ docker search nginx
# Build an image from Dockerfile
$ docker build -t myapp:latest .
# Build with a specific Dockerfile
$ docker build -f Dockerfile.prod -t myapp:prod .Working with Containers
# Run a container
$ docker run nginx
# Run in detached mode (background)
$ docker run -d nginx
# Run with a name
$ docker run -d --name my-nginx nginx
# Run with port mapping (host:container)
$ docker run -d -p 8080:80 nginx
# Run with environment variables
$ docker run -d -e APP_ENV=production myapp
# Run interactively with a terminal
$ docker run -it ubuntu bash
# List running containers
$ docker ps
# List all containers (including stopped)
$ docker ps -a
# Stop a container
$ docker stop my-nginx
# Start a stopped container
$ docker start my-nginx
# Restart a container
$ docker restart my-nginx
# Remove a container
$ docker rm my-nginx
# Force remove a running container
$ docker rm -f my-nginx
# Remove all stopped containers
$ docker container pruneInspecting Containers
# View container logs
$ docker logs my-nginx
# Follow logs in real time
$ docker logs -f my-nginx
# Show last 50 lines of logs
$ docker logs --tail 50 my-nginx
# Execute a command inside running container
$ docker exec -it my-nginx bash
# Execute a single command
$ docker exec my-nginx nginx -t
# View container resource usage
$ docker stats
# Inspect container details
$ docker inspect my-nginx
# View container processes
$ docker top my-nginx
# Copy files from container to host
$ docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
# Copy files from host to container
$ docker cp ./nginx.conf my-nginx:/etc/nginx/nginx.conf6. Writing Your First Dockerfile
A Dockerfile is a set of instructions that Docker follows to build your image. Each instruction creates a new layer in the image.
Dockerfile Instructions
| Instruction | What it does |
|---|---|
FROM | Sets the base image |
WORKDIR | Sets the working directory |
COPY | Copies files from host to image |
ADD | Like COPY but also handles URLs and tar files |
RUN | Executes commands during build |
ENV | Sets environment variables |
EXPOSE | Documents which port the app uses |
CMD | Default command when container starts |
ENTRYPOINT | Main command that always runs |
VOLUME | Creates a mount point for volumes |
ARG | Build-time variables |
Example 1 — Simple Node.js App
# Use official Node.js image as base
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy package files first (for layer caching)
COPY package*.json ./
# Install dependencies
RUN npm install --production
# Copy application code
COPY . .
# Expose the port the app runs on
EXPOSE 3000
# Command to start the app
CMD ["node", "server.js"]Example 2 — Python Flask App
FROM python:3.11-slim
WORKDIR /app
# Install dependencies first (better caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy app code
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]Example 3 — Multi-Stage Build (Production Best Practice)
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Production image (much smaller)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Why multi-stage builds? The first stage installs all build tools and dependencies (large). The second stage only copies the final built files into a minimal image. Final image is 10x smaller with no build tools or source code exposed.
Build and Run Your Image
# Build the image
$ docker build -t myapp:latest .
# Run a container from your image
$ docker run -d -p 3000:3000 --name myapp myapp:latest
# Test it
$ curl http://localhost:30007. Docker Volumes — Persisting Data
By default, when a container is deleted, all data inside it is lost. Volumes solve this by storing data outside the container.
Types of Storage in Docker
- Volumes — managed by Docker, stored in /var/lib/docker/volumes/. Best for production.
- Bind mounts — maps a host directory directly into a container. Best for development.
- tmpfs mounts — stored in memory only. Best for sensitive temporary data.
Working with Volumes
# Create a named volume
$ docker volume create mydata
# List volumes
$ docker volume ls
# Run container with a volume
$ docker run -d -v mydata:/var/lib/postgresql/data postgres
# Run container with a bind mount (dev use)
$ docker run -d -v $(pwd):/app myapp
# Inspect a volume
$ docker volume inspect mydata
# Remove a volume
$ docker volume rm mydata
# Remove all unused volumes
$ docker volume pruneReal World Example — PostgreSQL with Persistent Data
# Without volume — data lost when container is removed!
$ docker run -d postgres
# With volume — data persists across container restarts
$ docker run -d \
--name postgres-db \
-e POSTGRES_PASSWORD=mypassword \
-e POSTGRES_DB=myapp \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:158. Docker Networking
Docker networking allows containers to communicate with each other and with the outside world.
Default Network Drivers
- bridge — default network for containers on the same host. Containers can communicate by container name.
- host — container shares the host's network stack. No isolation.
- none — no networking. Fully isolated container.
- overlay — connects containers across multiple Docker hosts. Used in Docker Swarm.
Working with Networks
# List networks
$ docker network ls
# Create a custom network
$ docker network create myapp-network
# Run containers on the same network
$ docker run -d --network myapp-network --name db postgres
$ docker run -d --network myapp-network --name app myapp
# Now "app" container can reach "db" container using hostname "db"
$ docker exec app ping db
# Connect a running container to a network
$ docker network connect myapp-network my-nginx
# Inspect a network
$ docker network inspect myapp-network
# Remove a network
$ docker network rm myapp-network9. Docker Compose — Multi-Container Apps
Real applications rarely run as a single container. A typical web app needs a web server, a database, a cache, and maybe a queue. Docker Compose lets you define and run multi-container applications using a single YAML file.
docker-compose.yml — Full Web App Example
version: '3.8'
services:
# Web application
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
volumes:
- ./logs:/app/logs
restart: unless-stopped
# PostgreSQL database
db:
image: postgres:15
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
# Redis cache
redis:
image: redis:7-alpine
restart: unless-stopped
# Nginx reverse proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
restart: unless-stopped
volumes:
postgres-data:Docker Compose Commands
# Start all services
$ docker compose up
# Start in background
$ docker compose up -d
# Stop all services
$ docker compose down
# Stop and remove volumes (careful!)
$ docker compose down -v
# View logs
$ docker compose logs
# Follow logs for a specific service
$ docker compose logs -f app
# Scale a service
$ docker compose up -d --scale app=3
# Rebuild images
$ docker compose up -d --build
# View running services
$ docker compose ps
# Execute command in a service
$ docker compose exec app bash10. Docker in CI/CD Pipelines
In real DevOps work, Docker is at the heart of every CI/CD pipeline. Here is how a typical pipeline uses Docker:
# GitHub Actions — Build, Test, and Push Docker Image
name: Docker CI/CD
on:
push:
branches: [main]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Run tests inside container
run: docker run myapp:${{ github.sha }} npm test
- name: Push to Docker Hub
run: |
docker tag myapp:${{ github.sha }} vishwa/myapp:latest
docker push vishwa/myapp:latest
- name: Deploy to server
run: |
docker pull vishwa/myapp:latest
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 80:3000 vishwa/myapp:latest11. Docker Best Practices
Use specific image tags — never use latest in production
# Bad — unpredictable, could break with updates
FROM node:latest
# Good — pinned to a specific version
FROM node:18.19-alpine3.19Use .dockerignore to keep images small
# .dockerignore
node_modules
.git
.env
*.log
dist
coverage
README.mdOne process per container
Don't run your database and web server in the same container. Each container should do one thing. Use Docker Compose to link multiple single-purpose containers.
Run as non-root user
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
CMD ["node", "server.js"]Use multi-stage builds for smaller production images
As shown earlier — build in one stage, copy only what you need to the final image.
Order Dockerfile instructions for better caching
# Bad — copies all files first, cache breaks on any file change
COPY . .
RUN npm install
# Good — copies package.json first, npm install is cached unless dependencies change
COPY package*.json ./
RUN npm install
COPY . .Never store secrets in Docker images
Use environment variables, Docker secrets, or a secrets manager like AWS Secrets Manager or HashiCorp Vault.
Always add health checks
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 112. Common Docker Interview Questions
Q: What is the difference between a Docker image and a container?
An image is a read-only template used to create containers. A container is a running instance of an image. You can run many containers from the same image, just like creating many objects from the same class.
Q: What is the difference between CMD and ENTRYPOINT?
ENTRYPOINT defines the main command that always runs when the container starts. CMD provides default arguments that can be overridden at runtime. If you use both together, CMD acts as default arguments to ENTRYPOINT.
Q: How do you reduce Docker image size?
Use minimal base images (alpine), multi-stage builds, .dockerignore files, combine RUN commands to reduce layers, and avoid installing unnecessary packages.
Q: What is Docker Compose and when would you use it?
Docker Compose is a tool for defining and running multi-container applications using a YAML file. You use it when your application needs multiple services — like a web app with a database and cache — that need to work together.
Q: How does Docker networking work?
By default containers use a bridge network and are isolated from each other. You can create custom networks where containers can communicate using their container names as hostnames. The host network removes isolation and shares the host's network stack.
Q: What is a Docker volume and why is it needed?
A volume is a mechanism for persisting data generated by containers. Without volumes, all data inside a container is lost when it is deleted. Volumes store data outside the container's filesystem so it survives container restarts and deletions.
Q: What is a multi-stage build?
A multi-stage build uses multiple FROM instructions in one Dockerfile. Early stages handle building and compiling the application. The final stage copies only the built artifacts into a minimal base image — resulting in much smaller, more secure production images.
Q: What is the difference between COPY and ADD in a Dockerfile?
COPY simply copies files from host to image. ADD does everything COPY does but also supports extracting tar archives and downloading files from URLs. Best practice is to use COPY unless you specifically need ADD's extra features.
Q: How do you check why a container is crashing?
Use docker logs container-name to see output. Use docker inspect container-name to see detailed state. Use docker events to see real-time events. Check the exit code with docker ps -a.
Q: How do you share an image without using a registry?
# Save image to a tar file
$ docker save myapp:latest | gzip > myapp.tar.gz
# Load image from tar file on another machine
$ docker load < myapp.tar.gz13. Quick Reference Cheat Sheet
| Command | What it does |
|---|---|
docker pull image | Download image from registry |
docker build -t name . | Build image from Dockerfile |
docker run -d -p 80:80 image | Run container in background with port |
docker ps | List running containers |
docker ps -a | List all containers |
docker logs -f name | Follow container logs |
docker exec -it name bash | Shell into running container |
docker stop name | Stop a container gracefully |
docker rm name | Remove a stopped container |
docker images | List local images |
docker rmi image | Remove an image |
docker volume ls | List volumes |
docker network ls | List networks |
docker compose up -d | Start all services in background |
docker compose down | Stop and remove all services |
docker stats | Live resource usage |
docker inspect name | Detailed container info |
docker system prune | Remove all unused resources |
Wrapping Up
Docker is one of the most important skills in modern DevOps and software development. Once you understand containers, images, Dockerfiles, volumes, and networking — everything else in the DevOps ecosystem (Kubernetes, CI/CD, cloud deployments) becomes much easier to understand because they all build on Docker concepts.
Your Docker learning path:
- Week 1: Install Docker, run containers, learn basic commands
- Week 2: Write Dockerfiles, build and push your own images
- Week 3: Set up Docker Compose for a multi-container app
- Week 4: Integrate Docker into a CI/CD pipeline
- Month 2: Learn Kubernetes — the next step after Docker
Found this helpful? Share it with someone learning DevOps. Have a question or suggestion? Reach out at vishwasekar43@gmail.com
— Vishwa, DevOpsVault
Comments
Post a Comment