Docker for Beginners: Containers Explained Without the Jargon
Docker tutorial for beginners — learn containers vs VMs, Docker images, Dockerfiles, docker-compose, and how to containerize a real web application step by step.
Get more content like this on Telegram!
Daily AI tips, notes & resources — free
Docker for Beginners: Containers Explained Without the Jargon
The first time I tried to set up a Node.js project on a new laptop, it took three hours. Incompatible Node version. Wrong npm version. PostgreSQL installed differently than the documentation expected. Environment variables in the wrong place.
My colleague had the same project running in 5 minutes using Docker.
That was the moment I stopped avoiding Docker and started learning it.
Docker solves one of the most annoying problems in software development: "it works on my machine." With Docker, your application runs in an isolated environment that's identical everywhere — your laptop, your colleague's Windows machine, and your production server in the cloud.
This guide starts from zero: what containers are, how to build your first Dockerfile, how to run databases with Docker, and how to wire everything together with Docker Compose.
Containers vs Virtual Machines
The most common misconception: containers are not virtual machines.
Virtual Machine:
- Virtualizes an entire computer (CPU, memory, storage, OS)
- Runs its own kernel
- Heavy: 1–4 GB RAM per VM
- Slow start: minutes
- Complete isolation from host OS
Docker Container:
- Shares the host OS kernel
- Packages only the application and its dependencies
- Lightweight: 10–200 MB RAM
- Fast start: seconds
- Process-level isolation from host OS
Virtual Machines: Docker Containers:
┌──────────────────┐ ┌──────────────────┐
│ App A App B │ │ Container Container│
│ ┌──────┐┌──────┐│ │ ┌──────┐ ┌──────┐ │
│ │Guest ││Guest ││ │ │ App │ │ App │ │
│ │ OS ││ OS ││ │ │ Deps │ │ Deps │ │
│ └──────┘└──────┘│ │ └──────┘ └──────┘ │
│ Hypervisor │ │ Docker Engine │
│ Host OS │ │ Host OS │
└──────────────────┘ └──────────────────┘
For web development, Docker containers are almost always the right choice.
Installing Docker
Download Docker Desktop from docker.com — available for Mac, Windows, and Linux. It includes Docker Engine, Docker CLI, and Docker Compose.
Verify the installation:
docker --version
# Docker version 27.0.3
docker compose version
# Docker Compose version v2.29.1
Core Concepts: Image, Container, Registry
Image: A read-only blueprint containing the OS layer, your app's dependencies, and your app code. Built from a Dockerfile.
Container: A running instance of an image. You can run many containers from one image simultaneously.
Registry: A storage service for images. Docker Hub is the public registry. GitHub Container Registry (ghcr.io) is popular for private images.
# Pull an image from Docker Hub
docker pull node:20-alpine
# Run a container from an image
docker run node:20-alpine node --version
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# Stop a container
docker stop container_id
# Remove a container
docker rm container_id
# List images
docker images
# Remove an image
docker rmi image_name
Your First Dockerfile
A Dockerfile is a recipe for building a Docker image. Create one in your project root:
# syntax=docker/dockerfile:1
# Start from official Node.js 20 (Alpine = minimal Linux base)
FROM node:20-alpine
# Set working directory inside the container
WORKDIR /app
# Copy package files first (layer caching optimization)
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci --only=production
# Copy the rest of the application
COPY . .
# Expose the port your app listens on
EXPOSE 3000
# Command to run when container starts
CMD ["node", "server.js"]
Layer Caching Explained
Docker builds images in layers. Each instruction is a layer. If a layer hasn't changed, Docker reuses the cached version — this is why COPY package*.json ./ and RUN npm ci come before COPY . .:
# Layer 1: Base image (rarely changes)
FROM node:20-alpine
# Layer 2: Working directory (rarely changes)
WORKDIR /app
# Layer 3: Dependencies (changes only when package.json changes)
COPY package.json package-lock.json ./
RUN npm ci
# Layer 4: App code (changes frequently)
COPY . .
# Without this order: every code change rebuilds dependencies
# With this order: code changes only rebuild layer 4
Build and Run
# Build the image (-t tags it with a name)
docker build -t my-app:latest .
# Run a container from your image
docker run -p 3000:3000 my-app:latest
# ↑ ↑
# host:port container:port
# Run in background (-d = detached)
docker run -d -p 3000:3000 --name my-app-container my-app:latest
# View logs
docker logs my-app-container
docker logs -f my-app-container # Follow (live)
# Open a shell inside the container (debugging)
docker exec -it my-app-container sh
.dockerignore
Like .gitignore, but for Docker — exclude files from the build context:
node_modules
.git
.env
.env.local
npm-debug.log
dist
build
*.md
Dockerfile
.dockerignore
Without this, COPY . . would copy node_modules (hundreds of MB) into the image, defeating the purpose of RUN npm ci.
Docker Compose: Multiple Services Together
Most web apps need multiple services. Here's a docker-compose.yml for a Node.js app with PostgreSQL and Redis:
# docker-compose.yml
version: '3.9'
services:
# Your web application
app:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: development
DATABASE_URL: postgresql://postgres:password@db:5432/myapp
REDIS_URL: redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
volumes:
- .:/app # Mount code for hot reload in dev
- /app/node_modules # Don't mount node_modules from host
# PostgreSQL database
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data # Persist data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
retries: 5
# Redis cache
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data: # Named volume — persists between container restarts
Docker Compose Commands
# Start all services (build if needed)
docker compose up
# Start in background
docker compose up -d
# Rebuild and start
docker compose up --build
# Stop all services
docker compose down
# Stop and remove volumes (clears database)
docker compose down -v
# View logs for all services
docker compose logs
# View logs for one service
docker compose logs app
# Run a command in a service
docker compose exec app sh
docker compose exec db psql -U postgres myapp
Development vs Production Dockerfiles
For development, you want hot reload. For production, you want a minimal, fast image:
# Dockerfile.prod
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Multi-stage: final image only includes built output
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
Multi-stage builds produce much smaller production images because build tools, TypeScript, and source files aren't included.
For understanding the SQL databases you'll run with Docker, our SQL for web developers guide covers everything you need. For the HTTP protocol that powers your containerized apps, see our HTTP vs HTTPS guide.
Frequently Asked Questions
What is Docker?
A platform for running applications in containers — isolated, portable environments that package your app with its dependencies.
Container vs VM?
Containers share the host OS kernel and are lightweight (MB, seconds to start). VMs virtualize a full OS and are heavy (GB, minutes to start).
Image vs Container?
Image is the blueprint (read-only). Container is a running instance. Many containers can run from one image.
What is Docker Compose?
Manages multiple containers together — defines services, networks, and volumes in one YAML file. docker compose up starts everything.
Do web developers need Docker?
Increasingly yes. It eliminates "works on my machine" problems, is standard in CI/CD pipelines, and is the foundation of modern cloud deployment.
Frequently Asked Questions
AiTechWorlds Team
✓ Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
Understanding APIs: A Beginner's Story About How Apps Talk
API tutorial for beginners — understand what APIs are, how REST APIs work, HTTP methods, JSON, authentication, and how to call APIs in JavaScript with real examples.
The Web Developer's Guide to Chrome DevTools (Hidden Features)
Chrome DevTools guide for web developers — master the Elements panel, Network tab, Console, Performance profiler, and hidden features most developers never use.
CSS Grid vs Flexbox: When to Use Which Layout Method
CSS Grid vs Flexbox explained clearly — understand the difference, when each layout method excels, and how to choose the right one for every UI pattern.
Git for Beginners: Stop Fearing Version Control, Start Loving It
Git tutorial for beginners — learn the essential git commands, branching, merging, and GitHub workflow with real examples that make version control click.