Contents

Running Flask on Kubernetes with Minikube: From Docker Image to Live Pods

Step-by-step guide to containerizing a Flask app, deploying it to Minikube, and validating pods and services

Website Visitors:

Building a Flask Image for Minikube

  1. Write the application
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# app.py
from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def home():
    return f"Running from pod {os.getenv('POD_NAME', 'unknown')}"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)
  1. Create the Dockerfile
1
2
3
4
5
6
FROM python:3.9-slim
WORKDIR /app
COPY app.py .
RUN pip install flask
EXPOSE 80
CMD ["python", "app.py"]
  1. Build the image inside Minikube’s Docker daemon
1
docker build -t k8s-webserver-image .

We now have to add the image to minikube. We can do this in multiple ways. See detailed explanation but we can run eval $(minikube docker-env) simply run minikube image load k8s-webserver-image command. I’d prefer using the image load command as we don’t have to change back and forth between minikube docker and host docker.

So create app.py, Dockerfile files and run docker build command. This will create the custom image on your host. Next load it to minikube and continue below.

Kubernetes Deployment Manifest

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-web-app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: k8s-web-app
  template:
    metadata:
      labels:
        app: k8s-web-app
    spec:
      containers:
        - name: webapp
          image: k8s-webserver-image
          imagePullPolicy: IfNotPresent   # use the local image
          ports:
            - containerPort: 80
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
  • imagePullPolicy: IfNotPresent tells the kubelet to use the locally built image rather than attempting to pull from a remote registry.
  • The POD_NAME environment variable is populated from the pod’s metadata, enabling the Flask endpoint to display the pod identifier.

Deploying to Minikube

1
kubectl apply -f k8s-deployment.yaml

The deployment creates three pods, each running the Flask container.

Validating the Application

1. Verify pod status

1
kubectl get pods -l app=k8s-web-app

All pods should show Running and READY = 1/1.

2. Check container logs

1
2
POD=$(kubectl get pods -l app=k8s-web-app -o jsonpath='{.items[0].metadata.name}')
kubectl logs "$POD"

Logs must contain the Flask startup message (* Running on http://0.0.0.0:80/).

3. Expose the service (NodePort)

1
kubectl expose deployment k8s-web-app-deployment --type=NodePort --port=80

Retrieve the allocated port:

1
NODEPORT=$(kubectl get svc k8s-web-app-deployment -o jsonpath='{.spec.ports[0].nodePort}')

4. Curl the endpoint from the host

1
curl http://$(minikube ip):$NODEPORT

Expected output: Running from pod <pod-name>.

5. Alternative: port‑forward

1
2
kubectl port-forward deployment/k8s-web-app-deployment 8080:80 &
curl http://localhost:8080

Same expected output confirms the pod’s environment variable is correctly injected.

6. Verify POD_NAME inside a pod

1
kubectl exec -it "$POD" -- printenv POD_NAME

The command prints the pod’s metadata name, confirming the env mapping works.

Common Pitfalls

  • Missing __name__ – The Flask app must be instantiated with Flask(__name__). Using a placeholder (**name**) prevents the application from starting.
  • Image not found – Deploying without building the image inside Minikube leads to ErrImagePull. Building with minikube docker-env and setting imagePullPolicy: IfNotPresent resolves the issue.
  • Incorrect YAML indentation – YAML is whitespace‑sensitive; ensure env, ports, and imagePullPolicy are properly nested under containers.

By following the build, deployment, and validation steps above, the Flask application runs reliably on Minikube without external container registries.

Using Docker with Minikube: A Practical Guide

When working with Minikube, a lightweight Kubernetes environment, understanding how Docker interacts with it is crucial.

Minikube’s Docker Environment

Minikube can run its own Docker daemon inside the VM or container that hosts the cluster. This is separate from your local Docker installation. To make your shell use Minikube’s Docker instead of your host’s Docker, run:

1
eval $(minikube docker-env)
  • minikube docker-env prints environment variables that point Docker commands to Minikube’s daemon.

  • eval $(...) applies these variables to your current shell.

  • After this, docker build and docker run commands create images directly inside Minikube, making them immediately available for Kubernetes deployments.

To revert to your local Docker, run:

1
eval $(minikube docker-env -u)

Why Minikube Has Its Own Docker

Kubernetes requires a container runtime (Docker, containerd, or CRI-O). Minikube bundles one inside its environment, often Docker, but newer versions may use containerd internally. Even then, it usually provides a Docker interface for building images.

You can check the container runtime with:

1
kubectl get node -o jsonpath='{.items[0].status.nodeInfo.containerRuntimeVersion}'

How to Get Images into Minikube Kubernetes

Kubernetes nodes cannot see your local Docker images by default. There are three main approaches:

  1. Using Minikube’s Docker (fastest for local dev)
1
2
3
eval $(minikube docker-env)
docker build -t my-app .
kubectl apply -f deployment.yaml
  • Pros: Fast, simple, no registry needed

  • Cons: Only works inside Minikube, not portable

  1. Pushing to a Docker registry (real-world approach)
1
2
3
docker build -t my-app .
docker tag my-app username/my-app:v1
docker push username/my-app:v1
  • Pros: Portable, works in cloud clusters

  • Cons: Slower, requires registry access

  1. Using minikube image load (middle ground)
1
2
docker build -t my-app .
minikube image load my-app
  • Pros: Uses your local Docker without switching environments

  • Cons: Slightly slower than direct Minikube Docker

Tip: When using Minikube Docker or minikube image load, set imagePullPolicy: Never in your Kubernetes deployments to prevent unnecessary registry pulls.


Summary Table

Method Where Image Lives Kubernetes Can See It?
Local Docker Your machine No
Minikube Docker Inside Minikube Yes
Remote Registry Docker Hub, ECR, etc. Yes

This workflow allows developers to build, test, and deploy Kubernetes images locally with minimal friction, while still providing paths to production-ready deployments via container registries.

Your inbox needs more DevOps articles.

Subscribe to get our latest content by email.