Docker and Kubernetes for Beginners: Complete Guide to Container Technology
Containerization has revolutionized software development and deployment. Docker and Kubernetes are the leading technologies driving this transformation. This comprehensive guide takes you from complete beginner to confidently deploying applications using containers.
What Are Containers and Why Do They Matter?
The Problem Containers Solve
Traditional software deployment often suffers from "it works on my machine" syndrome. Applications behave differently across development, staging, and production environments due to differences in:
- Operating system versions
- Installed libraries and dependencies
- Environment variables and configurations
- Hardware specifications
Container Solution
Containers package applications with all their dependencies, libraries, and configuration files into a single, portable unit. This ensures consistent behavior across all environments.
Think of containers like shipping containers in the physical world — standardized, portable, and can be moved between ships, trucks, and trains without changing the contents.
Docker Fundamentals
What is Docker?
Docker is a platform for developing, shipping, and running applications in containers. It provides tools to create, manage, and deploy containers efficiently.
Key Docker Concepts
Images: Read-only templates used to create containers. Like a blueprint or recipe.
Containers: Running instances of images. Like houses built from blueprints.
Dockerfile: Text file containing instructions to build an image.
Registry: Storage for Docker images (Docker Hub is the default public registry).
Installing Docker
Windows/macOS: Download Docker Desktop from docker.com
Linux (Ubuntu):
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
Your First Docker Container
# Run a simple web server
docker run -d -p 8080:80 nginx
# Check running containers
docker ps
# View container logs
docker logs [container-id]
# Stop the container
docker stop [container-id]
Creating Custom Images with Dockerfile
Create a simple Python web application:
app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello from Docker!
'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
requirements.txt:
Flask==2.3.0
Dockerfile:
# Use official Python runtime as base image
FROM python:3.11-slim
# Set working directory in container
WORKDIR /app
# Copy requirements first (for better caching)
COPY requirements.txt .
# Install Python dependencies
RUN pip install -r requirements.txt
# Copy application code
COPY app.py .
# Expose port 5000
EXPOSE 5000
# Command to run the application
CMD ["python", "app.py"]
Build and run the image:
# Build the image
docker build -t my-python-app .
# Run the container
docker run -d -p 5000:5000 my-python-app
# Test the application
curl http://localhost:5000
Docker Compose for Multi-Container Applications
Docker Compose manages multiple containers as a single application.
docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
depends_on:
- redis
environment:
- REDIS_HOST=redis
redis:
image: redis:alpine
ports:
- "6379:6379"
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
Running with Compose:
# Start all services
docker-compose up -d
# View running services
docker-compose ps
# View logs
docker-compose logs web
# Stop all services
docker-compose down
Introduction to Kubernetes
What is Kubernetes?
Kubernetes (K8s) is a container orchestration platform that automates deployment, scaling, and management of containerized applications. While Docker runs containers on a single machine, Kubernetes manages containers across multiple machines (clusters).
Why Do You Need Kubernetes?
As applications grow, manual container management becomes impractical. Kubernetes provides:
- Automatic scaling based on demand
- Self-healing (restarts failed containers)
- Load balancing and service discovery
- Rolling updates with zero downtime
- Resource management and allocation
Key Kubernetes Concepts
Cluster: Set of machines (nodes) running Kubernetes
Nodes: Individual machines in the cluster
Pods: Smallest deployable units (contain one or more containers)
Deployments: Manage replicated pods
Services: Expose pods to network traffic
ConfigMaps/Secrets: Manage configuration and sensitive data
Setting Up a Local Kubernetes Environment
Option 1: Minikube
# Install minikube (macOS)
brew install minikube
# Start local cluster
minikube start
# Check cluster status
kubectl cluster-info
Option 2: Docker Desktop
Enable Kubernetes in Docker Desktop settings. This provides a simple single-node cluster for learning.
Your First Kubernetes Application
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: python-app
template:
metadata:
labels:
app: python-app
spec:
containers:
- name: python-app
image: my-python-app:latest
ports:
- containerPort: 5000
env:
- name: ENV
value: "production"
service.yaml:
apiVersion: v1
kind: Service
metadata:
name: python-app-service
spec:
selector:
app: python-app
ports:
- port: 80
targetPort: 5000
type: LoadBalancer
Deploy to Kubernetes:
# Apply deployment and service
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
# Check deployments
kubectl get deployments
# Check pods
kubectl get pods
# Check services
kubectl get services
# View pod logs
kubectl logs [pod-name]
# Scale the deployment
kubectl scale deployment python-app-deployment --replicas=5
Kubernetes Architecture Deep Dive
Control Plane Components
API Server: Frontend for Kubernetes control plane
etcd: Key-value store for cluster data
Scheduler: Assigns pods to nodes
Controller Manager: Runs controller processes
Node Components
kubelet: Agent that communicates with control plane
Container Runtime: Software that runs containers (Docker, containerd)
kube-proxy: Network proxy for services
Production Best Practices
Docker Best Practices
1. Use Multi-Stage Builds
# Build stage
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Production stage
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
2. Don't Run as Root
FROM python:3.11-slim
# Create non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Set ownership and switch to user
COPY --chown=appuser:appuser . /app
USER appuser
WORKDIR /app
CMD ["python", "app.py"]
3. Use .dockerignore
# .dockerignore
node_modules
.git
.gitignore
README.md
Dockerfile
.dockerignore
Kubernetes Best Practices
1. Resource Limits
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
2. Health Checks
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 5000
initialDelaySeconds: 5
periodSeconds: 5
3. Use Namespaces
# Create namespace
kubectl create namespace production
# Deploy to specific namespace
kubectl apply -f deployment.yaml -n production
Real-World Example: Deploying a Full Application
Let's deploy a complete web application with database and caching:
Database (PostgreSQL):
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_DB
value: "myapp"
- name: POSTGRES_USER
value: "user"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
Application with Redis Cache:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: my-web-app:v2
ports:
- containerPort: 5000
env:
- name: DATABASE_URL
value: "postgresql://user:password@postgres:5432/myapp"
- name: REDIS_URL
value: "redis://redis:6379"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
Monitoring and Troubleshooting
Essential kubectl Commands
# Get cluster information
kubectl cluster-info
# Describe resources
kubectl describe pod [pod-name]
kubectl describe service [service-name]
# View logs
kubectl logs -f [pod-name]
kubectl logs --previous [pod-name]
# Execute commands in containers
kubectl exec -it [pod-name] -- /bin/bash
# Port forwarding for testing
kubectl port-forward pod/[pod-name] 8080:5000
# View resource usage
kubectl top nodes
kubectl top pods
Common Troubleshooting Scenarios
Pod stuck in Pending state:
- Check if sufficient resources are available
- Verify image names and availability
- Check node selectors and tolerations
Container crashes repeatedly:
- Examine container logs
- Check resource limits
- Verify health check endpoints
Service not accessible:
- Verify selector labels match pod labels
- Check port configurations
- Test service endpoints
Next Steps and Advanced Topics
Container Orchestration Patterns
- Helm charts for package management
- Ingress controllers for advanced routing
- Operators for complex application management
- Service mesh (Istio) for microservices communication
Production Considerations
- Security scanning and vulnerability management
- CI/CD integration with container registries
- Multi-environment promotion strategies
- Backup and disaster recovery
Conclusion
Docker and Kubernetes represent a paradigm shift in application deployment and management. While the learning curve is significant, the benefits of consistency, scalability, and reliability make containerization essential for modern software development.
Start with Docker to understand containers, then progress to Kubernetes for orchestration. Practice with local environments before attempting production deployments. The container ecosystem is vast and constantly evolving, but mastering these fundamentals provides a solid foundation for advanced topics.
Remember: containers solve real problems, but they also introduce complexity. Evaluate whether containerization benefits your specific use case before adopting these technologies.