top of page

Containerize and Deploy: A Small App With Docker and Kubernetes (2026)

2 days ago
3 min read

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:3000

Here'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.0

Step 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: 3000

Step 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: 3000

Step 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-service

Here'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.

Recommended Products For This Post
 
 
 

Recent Posts

See All

Comments


© 2026 by neoaitech.com

  • Linkedin
  • Facebook
  • Twitter
  • Instagram

B608, 11 K County, Pune, Maharashtra, India

bottom of page