Téléverser les fichiers vers "z2"
This commit is contained in:
parent
b868e51ed4
commit
0ed027d8f6
12
z2/Dockerfile
Normal file
12
z2/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM python:3.9-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY app.py .
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
|
31
z2/README.md
Normal file
31
z2/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Shopping List Web App on Kubernetes (Local)
|
||||
|
||||
This project deploys a Flask-based shopping list app with PostgreSQL on a local Kubernetes cluster (Docker Desktop).
|
||||
|
||||
## Prerequisites
|
||||
- Docker Desktop with Kubernetes enabled
|
||||
- kubectl configured for `docker-desktop` context
|
||||
|
||||
## Files
|
||||
- `namespace.yaml`: Kubernetes namespace
|
||||
- `persistent-storage.yaml`: PVC for Postgres data
|
||||
- `postgres-deployment.yaml` / `postgres-service.yaml`: Postgres setup
|
||||
- `deployment.yaml` / `service.yaml`: Web app setup
|
||||
- `prepare-app.sh`: build Docker image
|
||||
- `start-app.sh`: apply Kubernetes resources
|
||||
- `stop-app.sh`: delete all resources
|
||||
|
||||
## Usage
|
||||
1. Build the image:
|
||||
```bash
|
||||
./prepare-app.sh
|
||||
|
||||
2. Deploy to Kubernetes:
|
||||
```bash
|
||||
./start-app.sh
|
||||
|
||||
3. Access the app:
|
||||
Open http://localhost:80 in your browser
|
||||
|
||||
4. Clean up :
|
||||
./stop-app.sh
|
112
z2/app.py
Normal file
112
z2/app.py
Normal file
@ -0,0 +1,112 @@
|
||||
from flask import Flask, request, redirect, url_for, render_template_string
|
||||
import os
|
||||
import psycopg2
|
||||
from psycopg2 import pool
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
DB_HOST = os.getenv('DB_HOST', 'localhost')
|
||||
DB_PORT = os.getenv('DB_PORT', '5432')
|
||||
DB_NAME = os.getenv('DB_NAME', 'postgres')
|
||||
DB_USER = os.getenv('DB_USER', 'postgres')
|
||||
DB_PASS = os.getenv('DB_PASS', 'postgres')
|
||||
|
||||
connection_pool = psycopg2.pool.SimpleConnectionPool(
|
||||
1, 10,
|
||||
host=DB_HOST,
|
||||
port=DB_PORT,
|
||||
database=DB_NAME,
|
||||
user=DB_USER,
|
||||
password=DB_PASS
|
||||
)
|
||||
|
||||
# Initialize database schema
|
||||
with connection_pool.getconn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('''
|
||||
CREATE TABLE IF NOT EXISTS shopping_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
item TEXT NOT NULL,
|
||||
quantity INTEGER DEFAULT 1,
|
||||
purchased BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
''')
|
||||
conn.commit()
|
||||
|
||||
HTML = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Shopping List</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Shopping List</h1>
|
||||
<form action="/add" method="post">
|
||||
<input name="item" placeholder="Item" required>
|
||||
<input name="quantity" type="number" value="1" min="1">
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
<ul>
|
||||
{% for id, name, qty, done in items %}
|
||||
<li>
|
||||
{{ name }} ({{ qty }})
|
||||
{% if not done %}
|
||||
<form action="/toggle/{{ id }}" method="post" style="display:inline">
|
||||
<button type="submit">Mark Purchased</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form action="/toggle/{{ id }}" method="post" style="display:inline">
|
||||
<button type="submit">Unmark</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<form action="/delete/{{ id }}" method="post" style="display:inline">
|
||||
<button type="submit">Delete</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
conn = connection_pool.getconn()
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("SELECT id, item, quantity, purchased FROM shopping_items ORDER BY purchased, id")
|
||||
items = cur.fetchall()
|
||||
connection_pool.putconn(conn)
|
||||
return render_template_string(HTML, items=items)
|
||||
|
||||
@app.route('/add', methods=['POST'])
|
||||
def add_item():
|
||||
item = request.form['item']
|
||||
qty = int(request.form.get('quantity', 1))
|
||||
conn = connection_pool.getconn()
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("INSERT INTO shopping_items (item, quantity) VALUES (%s, %s)", (item, qty))
|
||||
conn.commit()
|
||||
connection_pool.putconn(conn)
|
||||
return redirect(url_for('index'))
|
||||
|
||||
@app.route('/toggle/<int:item_id>', methods=['POST'])
|
||||
def toggle_item(item_id):
|
||||
conn = connection_pool.getconn()
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("UPDATE shopping_items SET purchased=NOT purchased WHERE id=%s", (item_id,))
|
||||
conn.commit()
|
||||
connection_pool.putconn(conn)
|
||||
return redirect(url_for('index'))
|
||||
|
||||
@app.route('/delete/<int:item_id>', methods=['POST'])
|
||||
def delete_item(item_id):
|
||||
conn = connection_pool.getconn()
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("DELETE FROM shopping_items WHERE id=%s", (item_id,))
|
||||
conn.commit()
|
||||
connection_pool.putconn(conn)
|
||||
return redirect(url_for('index'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5000)
|
50
z2/deployment.yaml
Normal file
50
z2/deployment.yaml
Normal file
@ -0,0 +1,50 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
namespace: my-app
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
initContainers:
|
||||
- name: wait-for-postgres
|
||||
image: busybox
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
until nc -z postgres 5432; do
|
||||
echo "Waiting for PostgreSQL..."
|
||||
sleep 2
|
||||
done
|
||||
containers:
|
||||
- name: web
|
||||
# use the LOCAL image you just built, not the one on Docker Hub
|
||||
image: simple-web-app:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
env:
|
||||
- name: DB_HOST
|
||||
value: postgres
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: DB_NAME
|
||||
value: postgres
|
||||
- name: DB_USER
|
||||
value: postgres
|
||||
- name: DB_PASS
|
||||
value: postgres
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 5000
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
4
z2/namespace.yaml
Normal file
4
z2/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-app
|
12
z2/persistent-storage.yaml
Normal file
12
z2/persistent-storage.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data-pvc
|
||||
namespace: my-app
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: docker-desktop
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
33
z2/postgres-deployment.yaml
Normal file
33
z2/postgres-deployment.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: my-app
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:14
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: postgres
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: postgres
|
||||
- name: POSTGRES_DB
|
||||
value: postgres
|
||||
volumeMounts:
|
||||
- name: postgres-storage
|
||||
mountPath: /var/lib/postgresql/data
|
||||
volumes:
|
||||
- name: postgres-storage
|
||||
emptyDir: {}
|
12
z2/postgres-service.yaml
Normal file
12
z2/postgres-service.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: my-app
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
clusterIP: None
|
11
z2/prepare-app.sh
Normal file
11
z2/prepare-app.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Prepare the environment: build Docker image
|
||||
|
||||
set -e
|
||||
|
||||
IMAGE_NAME="simple-web-app:latest"
|
||||
|
||||
echo "Building Docker image ${IMAGE_NAME}..."
|
||||
docker build -t ${IMAGE_NAME} .
|
||||
|
||||
echo "Preparation complete."
|
4
z2/requirements.txt
Normal file
4
z2/requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Flask>=2.0.0
|
||||
Werkzeug>=2.0.0
|
||||
gunicorn>=20.1.0
|
||||
psycopg2-binary>=2.9.3
|
13
z2/service.yaml
Normal file
13
z2/service.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web
|
||||
namespace: my-app
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: web
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 5000
|
||||
nodePort: 30080
|
29
z2/start-app.sh
Normal file
29
z2/start-app.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy the application to local Kubernetes
|
||||
|
||||
set -e
|
||||
|
||||
# Ensure kubectl uses the local Docker Desktop cluster
|
||||
kubectl config use-context docker-desktop
|
||||
|
||||
NAMESPACE="my-app"
|
||||
|
||||
echo "Creating namespace..."
|
||||
kubectl apply -f namespace.yaml
|
||||
|
||||
# (optional) if you’ve switched to emptyDir for Postgres storage, skip PVC
|
||||
# echo "Creating PersistentVolumeClaim..."
|
||||
# kubectl apply -f persistent-storage.yaml
|
||||
|
||||
echo "Deploying PostgreSQL..."
|
||||
kubectl apply -f postgres-deployment.yaml
|
||||
kubectl apply -f postgres-service.yaml
|
||||
|
||||
echo "Waiting for PostgreSQL pod(s) to be ready..."
|
||||
kubectl wait --for=condition=ready pod -l app=postgres -n ${NAMESPACE} --timeout=120s
|
||||
|
||||
echo "Deploying web application..."
|
||||
kubectl apply -f deployment.yaml
|
||||
kubectl apply -f service.yaml
|
||||
|
||||
echo "Deployment complete. Access the app at http://localhost:30080"
|
24
z2/stop-app.sh
Normal file
24
z2/stop-app.sh
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Remove the application from local Kubernetes
|
||||
|
||||
set -e
|
||||
|
||||
kubectl config use-context docker-desktop
|
||||
|
||||
NAMESPACE="my-app"
|
||||
|
||||
echo "Deleting web application..."
|
||||
kubectl delete -f service.yaml -n ${NAMESPACE} --ignore-not-found
|
||||
kubectl delete -f deployment.yaml -n ${NAMESPACE} --ignore-not-found
|
||||
|
||||
echo "Deleting PostgreSQL..."
|
||||
kubectl delete -f postgres-service.yaml -n ${NAMESPACE} --ignore-not-found
|
||||
kubectl delete -f postgres-deployment.yaml -n ${NAMESPACE} --ignore-not-found
|
||||
|
||||
echo "Deleting storage..."
|
||||
kubectl delete -f persistent-storage.yaml -n ${NAMESPACE} --ignore-not-found
|
||||
|
||||
echo "Deleting namespace..."
|
||||
kubectl delete -f namespace.yaml --ignore-not-found
|
||||
|
||||
echo "Cleanup complete."
|
Loading…
Reference in New Issue
Block a user