Containerize and Deploy: A Small App With Docker and Kubernetes (2026)
Reading about Docker and Kubernetes separately only gets you so far — the concepts click once you actually build something, containerize it, and watch it run on a cluster. This guide does exactly that: we'll write a tiny API, package it with Docker, and deploy it to Kubernetes with multiple replicas and a stable network address.
Step 1: A Minimal Application
Keep the app itself boring on purpose — the point of this walkthrough is the packaging and deployment, not the app logic. Here's a small Node.js API using Express:
// server.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({ message: 'Hello from inside a container!' });
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});// package.json
{
"name": "hello-api",
"version": "1.0.0",
"main": "server.js",
"scripts": { "start": "node server.js" },
"dependencies": { "express": "^4.19.2" }
}Step 2: Writing the Dockerfile
The Dockerfile describes how to turn this code into a self-contained image. Each line is a layer, cached independently — which is why dependencies are installed before the rest of the code is copied in:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]node:20-alpine is a good default base image for small Node apps — the Alpine Linux base keeps the final image size down, which means faster pulls when Kubernetes schedules your Pods.
Step 3: Build and Test Locally
Before touching Kubernetes at all, confirm the container works on its own:
docker build -t hello-api .
docker run -p 3000:3000 hello-api
curl localhost:3000Here's what that actually looks like running:
Step 4: Push the Image to a Registry
Kubernetes doesn't build images — it pulls existing ones. So before deploying, tag and push your image somewhere your cluster can reach, such as Docker Hub or GitHub Container Registry:
docker tag hello-api yourusername/hello-api:1.0
docker push yourusername/hello-api:1.0Step 5: Writing the Kubernetes Deployment
The Deployment tells Kubernetes what to run and how many copies to keep alive. Update the image: field to point at the one you just pushed:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-api
spec:
replicas: 3
selector:
matchLabels:
app: hello-api
template:
metadata:
labels:
app: hello-api
spec:
containers:
- name: hello-api
image: yourusername/hello-api:1.0
ports:
- containerPort: 3000Step 6: Exposing It With a Service
A Service gives your three replicas one stable address, and load-balances traffic across whichever Pods are currently healthy:
apiVersion: v1
kind: Service
metadata:
name: hello-api-service
spec:
type: LoadBalancer
selector:
app: hello-api
ports:
- port: 80
targetPort: 3000Step 7: Deploy and Verify
Apply both files, then check that everything came up correctly:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl get pods
kubectl get service hello-api-serviceHere's the full sequence, end to end:
Why This Matters: Self-Healing in Action
Try this once everything is running: delete one of the Pods manually with kubectl delete pod <pod-name>. Watch kubectl get pods immediately afterward — Kubernetes notices the mismatch between "3 desired" and "2 running," and starts a replacement automatically. No alert to respond to, no manual restart. That's the entire value proposition of Kubernetes in one small experiment.
Putting It All Together
The full picture, from a line of code to a scaled, self-healing deployment:
Next Steps
Add a readiness probe so Kubernetes only sends traffic to Pods that are actually ready to serve requests
Move the image tag into a CI/CD pipeline (see our GitHub Actions guide) so a git push triggers build, push, and deploy automatically
Add a ConfigMap for environment-specific configuration instead of hardcoding values
Try kubectl scale deployment hello-api --replicas=5 and watch new Pods appear in real time
Everything here — the Dockerfile, the two YAML files, the kubectl commands — is the same pattern used to deploy real production applications. The only thing that changes at scale is the size of the app; the workflow stays identical.

$50
Product Title
Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button

$50
Product Title
Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button.

$50
Product Title
Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button.


Comments