What is Docker?
Docker is an open-source platform that enables developers to automate the deployment of applications inside lightweight, portable containers. Released in 2013, Docker has revolutionized how we build, ship, and run applications by solving the age-old problem of “it works on my machine.”
A Docker container packages an application with all its dependencies, libraries, and configuration files, ensuring it runs consistently across any environment – from a developer’s laptop to production servers in the cloud.
Why Docker Matters for Web Developers
1. Consistency Across Environments
Docker eliminates the “works on my machine” problem:
– Development environment matches production exactly
– No more dependency conflicts
– Same behavior on any operating system
– Predictable deployments
2. Simplified Dependency Management
# Instead of installing Node.js, MongoDB, Redis, PostgreSQL locally # Just run: docker-compose up
3. Faster Onboarding
New team members can start developing immediately:
git clone project docker-compose up # Start coding - everything is configured
4. Isolation and Security
– Each application runs in its own container
– No conflicts between projects
– Easy to clean up (just remove container)
– Sandboxed execution environment
5. Microservices Architecture
– Each service in its own container
– Scale services independently
– Update without affecting others
– Mix technologies easily
Docker Core Concepts
Images
A Docker image is a read-only template containing application code, runtime, libraries, and dependencies.
# Pull an image from Docker Hub docker pull node:18 # List images docker images # Remove image docker rmi node:18
Containers
A container is a running instance of an image.
# Run a container docker run -d -p 3000:3000 --name myapp node:18 # List running containers docker ps # List all containers docker ps -a # Stop container docker stop myapp # Remove container docker rm myapp
Dockerfile
A Dockerfile defines how to build an image:
# Dockerfile for Node.js application FROM node:18 # Set working directory WORKDIR /app # Copy package files COPY package*.json ./ # Install dependencies RUN npm install # Copy application code COPY . . # Expose port EXPOSE 3000 # Start application CMD ["npm", "start"]
Docker Compose
Docker Compose manages multi-container applications:
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- DATABASE_URL=postgres://db:5432/myapp
depends_on:
- db
- redis
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7
volumes:
postgres_data:
Installing Docker
Windows
Download Docker Desktop from docker.com:
– Requires Windows 10/11 Pro or Enterprise
– WSL 2 backend recommended
– Includes Docker Compose
Mac
Download Docker Desktop for Mac:
– Works on Intel and Apple Silicon
– Includes Docker Compose
– Native performance
Linux
# Ubuntu/Debian curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # Add user to docker group sudo usermod -aG docker krithin # Install Docker Compose sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
Verify Installation
docker --version docker-compose --version docker run hello-world
Essential Docker Commands
Working with Containers
# Run container interactively docker run -it ubuntu bash # Run container in detached mode docker run -d nginx # Execute command in running container docker exec -it container_name bash # View container logs docker logs container_name docker logs -f container_name # Follow logs # Inspect container docker inspect container_name # View container resource usage docker stats
Working with Images
# Build image from Dockerfile docker build -t myapp:1.0 . # Tag image docker tag myapp:1.0 myapp:latest # Push image to registry docker push username/myapp:1.0 # Save image to file docker save myapp:1.0 > myapp.tar # Load image from file docker load < myapp.tar
Networking
# Create network docker network create mynetwork # List networks docker network ls # Connect container to network docker network connect mynetwork container_name # Inspect network docker network inspect mynetwork
Volumes
# Create volume docker volume create mydata # List volumes docker volume ls # Remove volume docker volume rm mydata # Run container with volume docker run -v mydata:/app/data myapp
Practical Examples for Web Development
Node.js Application
Dockerfile:
FROM node:18-alpine WORKDIR /app # Copy dependency files COPY package*.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Create non-root user RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 USER nodejs EXPOSE 3000 CMD ["node", "server.js"]
docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=mongodb://mongo:27017/myapp
depends_on:
- mongo
mongo:
image: mongo:7
volumes:
- mongo_data:/data/db
volumes:
mongo_data:
React Development Environment
Dockerfile.dev:
FROM node:18 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["npm", "start"]
docker-compose.yml:
version: '3.8'
services:
react-app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
Full-Stack Application (MERN)
version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- backend
backend:
build: ./backend
ports:
- "5000:5000"
volumes:
- ./backend:/app
- /app/node_modules
environment:
- MONGO_URL=mongodb://mongo:27017/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- mongo
- redis
mongo:
image: mongo:7
ports:
- "27017:27017"
volumes:
- mongo_data:/data/db
redis:
image: redis:7
ports:
- "6379:6379"
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- frontend
- backend
volumes:
mongo_data:
WordPress with MySQL
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: secret
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
db:
image: mysql:8
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: rootsecret
volumes:
- db_data:/var/lib/mysql
volumes:
wordpress_data:
db_data:
Docker Best Practices
1. Use Official Base Images
# Good - official Node.js image FROM node:18-alpine # Avoid - unknown source FROM someuser/node
2. Multi-Stage Builds
Reduce final image size:
# Build stage FROM node:18 AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Production stage FROM node:18-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules CMD ["node", "dist/server.js"]
3. Optimize Layer Caching
# Good - dependencies cached separately COPY package*.json ./ RUN npm install COPY . . # Bad - full rebuild on any file change COPY . . RUN npm install
4. Use .dockerignore
# .dockerignore node_modules npm-debug.log .git .env *.md .vscode
5. Run as Non-Root User
FROM node:18-alpine RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 USER nodejs # Rest of Dockerfile
6. Minimize Layers
# Good - single layer
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*
# Bad - multiple layers
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2
7. Use Specific Image Tags
# Good - specific version FROM node:18.17.0-alpine # Bad - unpredictable FROM node:latest
Docker Compose Commands
# Start services docker-compose up docker-compose up -d # Detached mode # Build images docker-compose build docker-compose build --no-cache # Stop services docker-compose stop docker-compose down # Stop and remove # View logs docker-compose logs docker-compose logs -f service_name # Execute command docker-compose exec service_name bash # List services docker-compose ps # Restart service docker-compose restart service_name
Development vs Production
Development Configuration
docker-compose.dev.yml:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app # Live code reloading
- /app/node_modules
environment:
- NODE_ENV=development
ports:
- "3000:3000"
Production Configuration
docker-compose.prod.yml:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
- NODE_ENV=production
restart: always
ports:
- "80:3000"
Usage:
# Development docker-compose -f docker-compose.dev.yml up # Production docker-compose -f docker-compose.prod.yml up -d
Docker Registry and Deployment
Docker Hub
# Login docker login # Tag image docker tag myapp:latest username/myapp:1.0 # Push to Docker Hub docker push username/myapp:1.0 # Pull from Docker Hub docker pull username/myapp:1.0
Private Registry
# Run private registry docker run -d -p 5000:5000 --name registry registry:2 # Tag for private registry docker tag myapp:latest localhost:5000/myapp:1.0 # Push to private registry docker push localhost:5000/myapp:1.0
Debugging Docker Containers
View Container Details
# Container logs docker logs container_name docker logs --tail 100 container_name # Container processes docker top container_name # Container resource usage docker stats container_name # Container details docker inspect container_name
Troubleshooting Common Issues
Container exits immediately:
docker logs container_name docker run -it image_name /bin/sh
Port already in use:
# Find process using port lsof -i :3000 # Or change port mapping docker run -p 3001:3000 myapp
Cannot connect to Docker daemon:
# Linux - add user to docker group sudo usermod -aG docker krithin # Restart Docker service sudo systemctl restart docker
Docker Security
Security Best Practices
1. Don't run as root
2. Scan images for vulnerabilities
3. Use minimal base images
4. Keep images updated
5. Don't store secrets in images
6. Limit container resources
Docker Secrets (Swarm)
# Create secret echo "db_password" | docker secret create db_pass - # Use in service docker service create \ --name myapp \ --secret db_pass \ myapp:latest
Docker Alternatives and Related Tools
- Podman: Daemonless container engine
- Kubernetes: Container orchestration
- Docker Swarm: Docker's native orchestration
- LXC: Linux containers
- containerd: Container runtime
Performance Optimization
Reduce Image Size
# Use alpine variants
FROM node:18-alpine # ~170MB vs ~900MB
# Remove development dependencies
RUN npm ci --only=production
# Clean up in same layer
RUN apt-get update && apt-get install -y package \
&& rm -rf /var/lib/apt/lists/*
Resource Limits
docker run -m 512m --cpus=2 myapp
# docker-compose.yml
services:
app:
deploy:
resources:
limits:
cpus: '2'
memory: 512M
Real-World Deployment Example
Complete production setup:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
app:
build: .
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://db:5432/myapp
depends_on:
- db
- redis
restart: always
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: always
redis:
image: redis:7-alpine
restart: always
volumes:
postgres_data:
Conclusion
Docker has become an essential tool for modern web development, offering:
- Consistent development environments
- Simplified dependency management
- Easy deployment and scaling
- Isolation and security
- Microservices architecture support
Whether you're building a simple application or a complex microservices system, Docker provides the tools and flexibility needed for efficient development and deployment.
Start with simple containers, gradually adopt Docker Compose for multi-container applications, and explore orchestration tools like Kubernetes as your needs grow.
For deploying Docker containers in production, consider reliable hosting providers like Hostinger or Cloudways that offer excellent Docker support and container hosting with managed services.