Docker & Kubernetes in the Cloud — Deployment Guide
Docker packages applications into lightweight, portable containers that run anywhere, while Kubernetes orchestrates those containers across clusters of machines — together, they form the backbone of modern cloud deployment.
What You’ll Learn
By the end of this tutorial, you’ll understand Docker images and containers, write Dockerfiles for your applications, create multi-container setups with Docker Compose, deploy to Kubernetes, and manage cloud-native applications on any cloud provider.
Why Docker & Kubernetes Matter
Over 80% of cloud-native organizations use containers in production. Docker eliminates “it works on my machine” by packaging code with all its dependencies. Kubernetes automates deployment, scaling, and management of containerized applications. At DodaTech, Durga Antivirus Pro uses Docker containers for isolated malware analysis environments.
Cloud Deployment Learning Path
flowchart LR
A[Cloud Basics] --> B[Docker]
B --> C[Kubernetes]
C --> D[Cloud Deployment]
D --> E{You Are Here}
style E fill:#f90,color:#fff
What Is Docker? (The “Why” First)
Think of Docker like shipping containers for software. Before shipping containers, cargo was loaded piece by piece — different sizes, shapes, and handling requirements. Shipping containers standardized everything: any container fits any ship, any truck, any train.
Docker does the same for software. Instead of saying “it works on my machine,” you package your app with all its dependencies into a Docker image. That image runs identically on your laptop, a test server, or a production cluster.
Docker vs Virtual Machine:
flowchart LR
subgraph "Virtual Machine"
A1[App A] --> B1[Guest OS]
C1[App B] --> D1[Guest OS]
B1 --> H1[Hypervisor]
D1 --> H1
H1 --> I1[Host OS]
end
subgraph "Docker Container"
A2[App A] --> B2[Docker Engine]
C2[App B] --> B2
B2 --> I2[Host OS]
end
| Aspect | VM | Docker Container |
|---|---|---|
| OS | Full guest OS per app | Shares host OS kernel |
| Size | GBs | MBs |
| Start time | Minutes | Seconds |
| Isolation | Strong (hardware-level) | Moderate (process-level) |
| Portability | Moderate | Excellent |
Your First Dockerfile
A Dockerfile is a recipe for building a Docker image:
# Dockerfile — A minimal Python web app
# Use an official Python runtime as the base image
FROM python:3.11-slim
# Set the working directory
WORKDIR /app
# Copy dependency file and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application code
COPY app.py .
# Expose the port the app runs on
EXPOSE 5000
# Command to run the application
CMD ["python", "app.py"]# app.py — Simple Flask app to containerize
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def home():
return """
<h1>Dockerized App</h1>
<p>Running inside a Docker container!</p>
<p>Host: {host}</p>
""".format(host=os.uname().nodename)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)# requirements.txt
flask==3.0.0Building and Running
# Build the Docker image
docker build -t dodatech-app:1.0 .
# Run the container
docker run -d -p 5000:5000 --name my-app dodatech-app:1.0
# Check running containers
docker ps
# View logs
docker logs my-app
# Stop the container
docker stop my-appExpected docker ps output:
CONTAINER ID IMAGE COMMAND STATUS PORTS
abc123def456 dodatech-app:1.0 "python app.py" Up 2 minutes 0.0.0.0:5000->5000/tcpDocker Commands Every Developer Needs
| Command | What It Does |
|---|---|
docker build -t name:tag . | Build an image from a Dockerfile |
docker run -d -p 8080:80 image | Run a container in detached mode, mapping ports |
docker ps | List running containers |
docker ps -a | List all containers (including stopped) |
docker stop <container> | Stop a running container |
docker rm <container> | Remove a stopped container |
docker images | List downloaded images |
docker rmi <image> | Remove an image |
docker pull <image> | Download an image from a registry |
docker logs <container> | See container logs |
docker exec -it <container> bash | Open a shell inside a running container |
docker compose up | Start multi-container setup |
Docker Compose — Multi-Container Apps
Docker Compose lets you define and run multi-container applications with a single YAML file:
# docker-compose.yml
# A web app with a database backend
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- DB_HOST=db
- DB_NAME=appdb
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=app
- POSTGRES_PASSWORD=secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:# Start everything with one command
docker compose up -d
# Check both services
docker compose ps
# View logs from both services
docker compose logs -f
# Stop everything
docker compose downWhat Is Kubernetes? (The “Why” First)
Docker runs containers on a single machine. Kubernetes (K8s) orchestrates containers across many machines — handling deployment, scaling, networking, and self-healing.
Think of Docker as a single engine and Kubernetes as a fleet of ships. Docker runs one container; Kubernetes runs thousands across a cluster.
Kubernetes Architecture
flowchart TD
subgraph "Kubernetes Cluster"
subgraph "Control Plane"
API[API Server]
Sched[Scheduler]
CM[Controller Manager]
ETCD[etcd]
end
subgraph "Node 1"
Kubelet1
Pod1[Pod: App A]
Pod2[Pod: App B]
end
subgraph "Node 2"
Kubelet2
Pod3[Pod: App C]
Pod4[Pod: App D]
end
end
API --> Kubelet1
API --> Kubelet2
Sched --> API
CM --> API
Key concepts:
- Pod — smallest deployable unit (one or more containers)
- Node — a worker machine (VM or physical)
- Cluster — set of nodes managed by the control plane
- Deployment — declares desired state (how many replicas)
- Service — stable network endpoint for pods
- ConfigMap/Secret — configuration data
Your First Kubernetes Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dodatech-web
spec:
replicas: 3 # Run 3 copies for high availability
selector:
matchLabels:
app: dodatech-web
template:
metadata:
labels:
app: dodatech-web
spec:
containers:
- name: web
image: dodatech-app:1.0
ports:
- containerPort: 5000
resources:
requests:
cpu: "100m" # Request 0.1 CPU
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
---
# Service — exposes the deployment on a stable IP
apiVersion: v1
kind: Service
metadata:
name: dodatech-web-service
spec:
type: LoadBalancer
selector:
app: dodatech-web
ports:
- port: 80
targetPort: 5000# Deploy to Kubernetes
kubectl apply -f deployment.yaml
# Check pods
kubectl get pods
# Check service
kubectl get service dodatech-web-service
# Scale to 5 replicas
kubectl scale deployment dodatech-web --replicas=5
# View logs
kubectl logs deployment/dodatech-web
# Delete everything
kubectl delete -f deployment.yamlDeploying to Cloud Kubernetes Services
AWS EKS
# Create EKS cluster (using eksctl)
eksctl create cluster \
--name dodatech-cluster \
--region us-east-1 \
--nodegroup-name standard \
--node-type t3.medium \
--nodes 3
# Deploy your app
kubectl apply -f deployment.yamlAzure AKS
# Create AKS cluster
az aks create \
--resource-group MyResourceGroup \
--name dodatech-aks \
--node-count 3 \
--enable-addons monitoring
# Get credentials
az aks get-credentials \
--resource-group MyResourceGroup \
--name dodatech-aks
# Deploy
kubectl apply -f deployment.yamlGCP GKE
# Create GKE cluster
gcloud container clusters create dodatech-gke \
--num-nodes=3 \
--zone=us-central1-a
# Get credentials
gcloud container clusters get-credentials dodatech-gke
# Deploy
kubectl apply -f deployment.yamlCommon Docker & Kubernetes Mistakes
1. Running Containers as Root
Running containers as root inside the container is a security risk. Use USER in Dockerfile to run as non-root.
2. Hardcoding Configuration in Images
Environment variables and config files should be injected at runtime, not baked into images. Use -e flags or ConfigMaps.
3. Not Pinning Image Tags
Using latest tag means unpredictable updates. Always pin to a specific version: python:3.11-slim not python:latest.
4. Over-Allocating Resources
Not setting resource requests and limits means one noisy neighbor pod can starve others. Always set CPU/memory limits.
5. Ignoring Pod Disruption Budgets
Without PDBs, cluster maintenance or upgrades can take down all your pods simultaneously.
6. Using : Instead of -- in Dockerfile Labels
Docker labels use = syntax: LABEL version="1.0" severity="critical". Incorrect syntax fails silently.
7. Not Using .dockerignore
Without .dockerignore, you’ll copy gigabytes of node_modules or .git into your image. Always exclude unnecessary files.
Practice Questions
1. What’s the difference between a Docker image and a container?
An image is a read-only template (the recipe). A container is a running instance of that image (the cooked meal). You can run multiple containers from the same image.
2. Why is Docker more lightweight than a virtual machine?
Containers share the host OS kernel instead of running a full guest OS per app. This means containers are smaller (MB vs GB) and start faster (seconds vs minutes).
3. What does Kubernetes do that Docker alone cannot?
Kubernetes orchestrates containers across multiple machines — handling deployment, scaling, networking, load balancing, self-healing, and rolling updates. Docker manages containers on a single machine.
4. What is a Kubernetes Pod?
The smallest deployable unit in Kubernetes — one or more containers that share network and storage. Usually you run one container per pod.
5. Challenge: Write a Dockerfile for a Node.js Express app.
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]Mini Project: Full CI/CD Pipeline
Create a complete CI/CD pipeline using Docker and Kubernetes:
# .github/workflows/deploy.yml (GitHub Actions)
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t dodatech-app:${{ github.sha }} .
- name: Push to registry
run: |
docker tag dodatech-app:${{ github.sha }} \
${{ secrets.REGISTRY }}/dodatech-app:latest
docker push ${{ secrets.REGISTRY }}/dodatech-app:latest
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/dodatech-web \
web=${{ secrets.REGISTRY }}/dodatech-app:latestFAQ
Try It Yourself
- Install Docker Desktop on your machine
- Build and run the Flask app from this tutorial
- Modify the app to return your name, rebuild, and re-run
- Push the image to Docker Hub:
docker push yourname/dodatech-app:1.0 - Create a
docker-compose.ymlthat adds Redis for caching
DodaTech uses this exact workflow for Doda Browser microservices — each service is a Docker container, orchestrated by Kubernetes on GKE.
What’s Next
What’s Next
Congratulations on completing this Docker & Kubernetes tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro