Docker and Kubernetes Basics: Containers Explained for Beginners
Updated 28 Oct 2026 3 min read
On this page 13 sections
Why containers
"It works on my machine" is a classic problem: your laptop and the server have different versions of languages, libraries and settings. A container packages your application together with everything it needs to run, so it behaves the same everywhere. Containers are lighter than virtual machines because they share the host's operating system kernel.
Docker is the most popular tool for building and running containers, and Kubernetes (K8s) manages many containers across many machines. These skills appear in almost every DevOps and backend job description.
Key Docker ideas
- Image: a read-only template (your app plus its dependencies)
- Container: a running instance of an image
- Dockerfile: the recipe that builds an image
- Registry: a store for images (Docker Hub, GitHub Container Registry, cloud registries)
- Volume: storage that outlives a container
- Network: how containers talk to each other
Your first Dockerfile
A small Node.js example:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Copying package*.json and installing dependencies before copying the rest of your code lets Docker reuse cached layers, so rebuilds are fast. A Python version looks similar: start from python:3.12-slim, copy requirements.txt, run pip install -r requirements.txt, copy the code and set the CMD.
Add a .dockerignore file (like .gitignore) to keep node_modules, .git and secrets out of the image.
Everyday Docker commands
docker build -t myapp:1.0 . # build an image
docker run -d -p 8080:3000 --name web myapp:1.0 # run it, map host:container ports
docker ps # list running containers
docker logs -f web # follow the logs
docker exec -it web sh # open a shell inside
docker stop web && docker rm web # stop and remove
docker images # list images
Never bake passwords or API keys into an image. Pass them at run time with environment variables or a secrets mechanism.
Docker Compose: several containers together
Most apps need an app container plus a database. Compose describes them in one file:
services:
web:
build: .
ports:
- "8080:3000"
environment:
DATABASE_URL: postgres://app:secret@db:5432/appdb
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
volumes:
- dbdata:/var/lib/postgresql/data
volumes:
dbdata:
Run everything with docker compose up -d and stop it with docker compose down. Containers reach each other by service name (db).
Good Docker practice
- Use small, official base images and pin versions
- Run as a non-root user where possible
- Use multi-stage builds to keep the final image small
- One main process per container
- Scan images for vulnerabilities
Kubernetes in plain words
Kubernetes keeps your desired state true: you say "run three copies of this container, expose them on port 80", and it starts them, replaces failed ones, and spreads them over machines.
Core objects
- Pod: the smallest unit; one or more containers that run together
- Deployment: manages a set of identical pods, rolling updates and rollbacks
- Service: a stable address that load-balances across pods
- Ingress: routes external HTTP traffic to services
- ConfigMap and Secret: configuration and sensitive values
- Namespace: a logical grouping of resources
- Node: a machine in the cluster
A minimal deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: youruser/myapp:1.0
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 3000
Apply it with kubectl apply -f web.yaml.
Essential kubectl commands
kubectl get pods # list pods
kubectl get deployments,services
kubectl describe pod <name> # events and details: first stop when something fails
kubectl logs <pod> # application logs
kubectl exec -it <pod> -- sh # shell in a pod
kubectl scale deployment web --replicas=4
kubectl rollout status deployment/web
kubectl rollout undo deployment/web # roll back a bad release
Practise locally with minikube or kind before touching a cloud cluster.
Production habits
- Add resource requests and limits, plus readiness and liveness probes
- Store configuration in ConfigMaps and Secrets, never in images
- Use rolling updates and keep rollbacks ready
- Monitor with metrics and logs (DevOps roadmap)
- Expect to learn Helm and infrastructure as code later
Interview questions
- Container vs virtual machine
- Image vs container
- What does a Dockerfile do? What are layers and caching?
- What is a Pod? Deployment vs Pod?
- How do Services route traffic?
- Rolling update vs rollback
- A pod is in
CrashLoopBackOff. How do you debug it? - How do you pass secrets to a container?
Practice plan
- Containerise a project you have already built
- Run it with Compose, together with a database
- Deploy it on a local Kubernetes cluster with two replicas
- Break it on purpose (bad image, failing probe) and debug it with
describeandlogs
Next steps
Pair this with Linux essentials and Git, then add the result to your portfolio.
Found this useful? Share it with a friend.