Count

# app.py
import os
import time
import redis
from flask import Flask

def get_ip():
    return os.getenv('MYREDIS_HOST', 'localhost')

app = Flask(__name__)
cache = redis.Redis(host=get_ip(), port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello from Docker! I have been seen {} times.\n'.format(count)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
        
# requirements.txt
flask
redis
        
# Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["python", "app.py"]
        
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
  labels:
    app: webapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp # let deployment know which pod for this deployment
  template: # configuration for pods
    metadata:
      labels:
        app: webapp # each pod has a unique name, but pods can share the same label
    spec:
      containers: # containers in a pod, usually add one container per pod
      - name: webapp
        image: lchenlangley/count # pull image from local
        imagePullPolicy: Never
        ports:
        - containerPort: 5000
        env:
        - name: MYREDIS_HOST
          value: redis-service
        
# app-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-service # service name accessed by app
spec:
  selector:
    app: webapp # match the pod labels
  ports:
    - protocol: TCP
      port: 5000 # service port
      targetPort: 5000 # pod port
        
# redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis # let deployment know which pod for this deployment
  template: # configuration for pods
    metadata:
      labels:
        app: redis # each pod has a unique name, but pods can share the same label
    spec:
      containers: # containers in a pod, usually add one container per pod
      - name: redisdb
        image: redis:alpine # pull image from Docker Hub
        ports:
        - containerPort: 6379
        
# redis-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-service # service name accessed by app
spec:
  selector:
    app: redis # match the pod labels
  ports:
    - protocol: TCP
      port: 6379 # service port
      targetPort: 6379 # pod port
        
Minikube
# select Kubernetes/minikube on Docker Desktop

# 1. Start minikube
minikube start
eval $(minikube docker-env) # point to inside of Minikube container
        
# 2. Create image in the registry of the Minikube container
docker build -t lchenlangley/count .
        
# 3. Deploy app on K8s cluster or minikube

# kubectl get all, search service name
kubectl create -f k8s # k8s is the directory of yaml files
        
# 4. Expore service port to user
kubectl port-forward svc/webapp-service 8000:5000 # [external port]:[service port]
        
# 5. Access app
http://localhost:8000/
        
# Cleaning Up
kubectl delete -f k8s
        
Reference
  • How to Run Locally Built Docker Images in Kubernetes