From d5da62d8002559ec19fe6b73c06b36384ff1fcb6 Mon Sep 17 00:00:00 2001 From: miklo Date: Sun, 23 Nov 2025 22:02:24 +0100 Subject: [PATCH] dockerize app --- .dockerignore | 8 +++++ Dockerfile | 19 +++++++++++ app.py | 79 +++++++++++++++++++++++++++++++++----------- docker-compose.yml | 17 ++++++++++ requirements.txt | 2 ++ templates/admin.html | 48 +++++++++++++++++++-------- templates/index.html | 26 +++++++++++---- 7 files changed, 161 insertions(+), 38 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f64cebf --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +__pycache__/ +*.pyc +*.pyo +.env +.vscode/ +.idea/ +queue.db +*.db diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e798ef5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.11-slim + +ENV PYTHONUNBUFFERED=1 \ + FLASK_ENV=production \ + FLASK_APP=app.py + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +RUN mkdir -p /data +VOLUME ["/data"] + +ENV DB_PATH=/data/queue.db + +CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app", "--workers", "3", "--worker-class", "gthread", "--threads", "4"] diff --git a/app.py b/app.py index b5b7838..bf3840f 100644 --- a/app.py +++ b/app.py @@ -2,9 +2,13 @@ from flask import Flask, render_template, request, redirect, url_for, g, jsonify import sqlite3 import os -DB = "queue.db" +DB = os.environ.get("DB_PATH", "queue.db") +ADMIN_SUFFIX = os.environ.get("ADMIN_URL", "admin").strip("/") +ADMIN_PATH = f"/{ADMIN_SUFFIX}" if ADMIN_SUFFIX else "/admin" + app = Flask(__name__) + def get_db(): db = getattr(g, "_db", None) if db is None: @@ -15,40 +19,51 @@ def get_db(): init_db(db) return db + def init_db(db): cur = db.cursor() - cur.execute("""CREATE TABLE items ( + cur.execute( + """CREATE TABLE items ( id INTEGER PRIMARY KEY AUTOINCREMENT, number TEXT, status TEXT -- 'waiting', 'called', 'done' - )""") + )""" + ) db.commit() + @app.teardown_appcontext def close_db(exc): db = getattr(g, "_db", None) if db: db.close() + # Main display for clients @app.route("/") def index(): db = get_db() - cur = db.execute("SELECT number FROM items WHERE status='called' ORDER BY id DESC LIMIT 1") + cur = db.execute( + "SELECT number FROM items WHERE status='called' ORDER BY id DESC LIMIT 1" + ) row = cur.fetchone() current = row["number"] if row else "" return render_template("index.html", current=current) + # API endpoint used by clients to poll current number (JSON) @app.route("/current") def current_api(): db = get_db() - cur = db.execute("SELECT number FROM items WHERE status='called' ORDER BY id DESC LIMIT 1") - row = cur.fetchone() - return jsonify(current=(row["number"] if row else "")) + cur = db.execute( + "SELECT number FROM items WHERE status='called' ORDER BY id" + ).fetchall() + nums = [r["number"] for r in cur] + return jsonify(current=nums) + # Admin UI: start/reset system by providing count of tickets (1..N) -@app.route("/admin", methods=["GET", "POST"]) +# @app.route("/admin", methods=["GET", "POST"]) def admin(): db = get_db() if request.method == "POST": @@ -56,30 +71,56 @@ def admin(): if action == "start": n = int(request.form.get("count", "0")) db.execute("DELETE FROM items") - for i in range(1, n+1): - db.execute("INSERT INTO items (number, status) VALUES (?, 'waiting')", (str(i),)) + for i in range(1, n + 1): + db.execute( + "INSERT INTO items (number, status) VALUES (?, 'waiting')", + (str(i),), + ) db.commit() elif action == "call": num = request.form.get("num") # mark chosen number as called - db.execute("UPDATE items SET status='called' WHERE number=? AND status='waiting'", (num,)) + db.execute( + "UPDATE items SET status='called' WHERE number=? AND status='waiting'", + (num,), + ) db.commit() elif action == "done": num = request.form.get("num") - db.execute("UPDATE items SET status='done' WHERE number=? AND status='called'", (num,)) + db.execute( + "UPDATE items SET status='done' WHERE number=? AND status='called'", + (num,), + ) db.commit() elif action == "reset": db.execute("DELETE FROM items") db.commit() + elif action == "return": + num = request.form.get("num") + if num: + # ustaw ponownie na 'waiting' tylko jeśli aktualnie było 'called' + db.execute("UPDATE items SET status='waiting' WHERE number=? AND status='called'", (num,)) + db.commit() return redirect(url_for("admin")) - cur_wait = db.execute("SELECT number FROM items WHERE status='waiting' ORDER BY id").fetchall() - cur_called = db.execute("SELECT number FROM items WHERE status='called' ORDER BY id").fetchall() - cur_done = db.execute("SELECT number FROM items WHERE status='done' ORDER BY id").fetchall() - return render_template("admin.html", - waiting=[r["number"] for r in cur_wait], - called=[r["number"] for r in cur_called], - done=[r["number"] for r in cur_done]) + cur_wait = db.execute( + "SELECT number FROM items WHERE status='waiting' ORDER BY id" + ).fetchall() + cur_called = db.execute( + "SELECT number FROM items WHERE status='called' ORDER BY id" + ).fetchall() + cur_done = db.execute( + "SELECT number FROM items WHERE status='done' ORDER BY id" + ).fetchall() + return render_template( + "admin.html", + waiting=[r["number"] for r in cur_wait], + called=[r["number"] for r in cur_called], + done=[r["number"] for r in cur_done], + ) + +app.add_url_rule(ADMIN_PATH, endpoint="admin", view_func=admin, methods=["GET", "POST"]) + if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7136e9a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.8" + +services: + queue: + image: "queue-app:latest" # zmień na registry/name:tag jeśli pobierasz z rejestru + ports: 5000 + volumes: + - queue_data:/data + environment: + - DB_PATH=/data/queue.db + - ADMIN_URL=admin-panel + restart: always + deploy: + replicas: 1 + +volumes: + queue_data: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..654a2b7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +Flask==2.3.2 +gunicorn==20.1.0 diff --git a/templates/admin.html b/templates/admin.html index b6fdde8..75a8d83 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -3,26 +3,40 @@ Panel admina — kolejka - +

Panel admina

-
+ - - + +
-
+

Oczekujące

{% for n in waiting %} -
+ - +
{% else %}

brak

@@ -32,11 +46,19 @@

Wywołane (obecne)

{% for n in called %} -
- {{n}} - - -
+
+ {{n}} + +
+ + +
+ +
+ + +
+
{% else %}

brak

{% endfor %} diff --git a/templates/index.html b/templates/index.html index 5333f6e..d840c68 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,23 +2,37 @@ - Wywoływany numer - + Wywoływane numery + -

Proszę podejść do okienka

-
-
+

Zapraszamy do stanowiska osoby z numerem:

+
-