Update app templates and routes
This commit is contained in:
@@ -16,6 +16,9 @@ RUN pip install --no-cache-dir -r requirements.txt \
|
||||
|
||||
COPY . .
|
||||
|
||||
# Ensure entrypoint is executable
|
||||
RUN chmod +x docker/entrypoint.sh
|
||||
|
||||
# Create runtime dirs (also mountable as volumes)
|
||||
RUN mkdir -p instance app/static/uploads
|
||||
|
||||
@@ -27,4 +30,4 @@ ENV FLASK_ENV=production \
|
||||
GUNICORN_BIND=0.0.0.0:8000
|
||||
|
||||
# Run via WSGI entrypoint
|
||||
CMD ["sh", "-c", "gunicorn -w ${GUNICORN_WORKERS} -b ${GUNICORN_BIND} wsgi:app"]
|
||||
CMD ["sh", "-c", "./docker/entrypoint.sh"]
|
||||
|
||||
15
README.md
15
README.md
@@ -71,10 +71,23 @@ environment variables via your process manager / secrets.
|
||||
|
||||
This repo includes a `docker-compose.yml` for a one-command startup.
|
||||
|
||||
On first run, the container will ensure the SQLite schema exists.
|
||||
If you provide `ADMIN_PASS`, it will also create/update the initial admin user.
|
||||
|
||||
```powershell
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
Create an admin on startup (recommended):
|
||||
|
||||
```powershell
|
||||
$env:ADMIN_EMAIL="you@example.com"
|
||||
$env:ADMIN_PASS="YourStrongPassword"
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
Or put these in a `.env` file used by Compose.
|
||||
|
||||
Run in the background:
|
||||
|
||||
```powershell
|
||||
@@ -217,5 +230,7 @@ If the reset email is not received:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from werkzeug.exceptions import RequestEntityTooLarge
|
||||
|
||||
from .extensions import db, login_manager
|
||||
from .models import AppSettings, User
|
||||
from .cli import init_db_command
|
||||
from .cli import ensure_db_command, init_db_command
|
||||
|
||||
|
||||
def create_app():
|
||||
@@ -85,6 +85,7 @@ def create_app():
|
||||
return db.session.get(User, int(user_id))
|
||||
|
||||
# CLI
|
||||
app.cli.add_command(ensure_db_command)
|
||||
app.cli.add_command(init_db_command)
|
||||
|
||||
# Blueprints
|
||||
|
||||
43
app/cli.py
43
app/cli.py
@@ -5,21 +5,11 @@ from .extensions import db
|
||||
from .models import AppSettings, User
|
||||
|
||||
|
||||
@click.command("init-db")
|
||||
@click.option(
|
||||
"--admin-email",
|
||||
required=False,
|
||||
default="beheer@alphen.cloud",
|
||||
show_default=True,
|
||||
help="Email for the initial admin",
|
||||
)
|
||||
@click.option("--admin-pass", required=True, help="Password for the initial admin")
|
||||
@with_appcontext
|
||||
def init_db_command(admin_email: str, admin_pass: str):
|
||||
"""Create tables and ensure an admin account exists."""
|
||||
def _ensure_schema_and_settings() -> None:
|
||||
"""Create tables + run lightweight SQLite migrations + ensure settings row exists."""
|
||||
db.create_all()
|
||||
|
||||
# Lightweight migration for older SQLite DBs: ensure User.email column exists.
|
||||
# Lightweight migration for older SQLite DBs: ensure columns exist.
|
||||
# This avoids requiring Alembic for this small project.
|
||||
try:
|
||||
cols = [r[1] for r in db.session.execute(db.text("PRAGMA table_info(user)")).fetchall()]
|
||||
@@ -50,6 +40,33 @@ def init_db_command(admin_email: str, admin_pass: str):
|
||||
db.session.add(AppSettings(id=1))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@click.command("ensure-db")
|
||||
@with_appcontext
|
||||
def ensure_db_command():
|
||||
"""Create tables / apply lightweight migrations.
|
||||
|
||||
This is useful for container startup where you want schema readiness,
|
||||
without requiring admin credentials.
|
||||
"""
|
||||
_ensure_schema_and_settings()
|
||||
click.echo("Database ready.")
|
||||
|
||||
|
||||
@click.command("init-db")
|
||||
@click.option(
|
||||
"--admin-email",
|
||||
required=False,
|
||||
default="beheer@alphen.cloud",
|
||||
show_default=True,
|
||||
help="Email for the initial admin",
|
||||
)
|
||||
@click.option("--admin-pass", required=True, help="Password for the initial admin")
|
||||
@with_appcontext
|
||||
def init_db_command(admin_email: str, admin_pass: str):
|
||||
"""Create tables and ensure an admin account exists."""
|
||||
_ensure_schema_and_settings()
|
||||
|
||||
admin_email = (admin_email or "").strip().lower()
|
||||
if not admin_email:
|
||||
raise click.UsageError("--admin-email is required")
|
||||
|
||||
@@ -7,9 +7,16 @@ services:
|
||||
environment:
|
||||
# Override in a .env file or your shell; this default is only for convenience.
|
||||
SECRET_KEY: "change-me"
|
||||
# Optional bootstrap (only runs if ADMIN_PASS is set)
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@admin.admin}
|
||||
ADMIN_PASS: ${ADMIN_PASS:-}
|
||||
# Optional overrides (the Dockerfile already defaults these)
|
||||
GUNICORN_WORKERS: "2"
|
||||
GUNICORN_BIND: "0.0.0.0:8000"
|
||||
# Entrypoint (from Dockerfile) runs:
|
||||
# - `flask ensure-db`
|
||||
# - optional `flask init-db` when ADMIN_PASS is set
|
||||
# - gunicorn
|
||||
volumes:
|
||||
# Persist SQLite DB and uploads on the host
|
||||
- ./instance:/app/instance
|
||||
|
||||
12
docker/entrypoint.sh
Normal file
12
docker/entrypoint.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
# Ensure DB schema exists
|
||||
flask --app app ensure-db
|
||||
|
||||
# Optional: create/update initial admin account
|
||||
if [ -n "${ADMIN_PASS:-}" ]; then
|
||||
flask --app app init-db --admin-email "${ADMIN_EMAIL:-admin@admin.admin}" --admin-pass "${ADMIN_PASS}"
|
||||
fi
|
||||
|
||||
exec gunicorn -w "${GUNICORN_WORKERS:-2}" -b "${GUNICORN_BIND:-0.0.0.0:8000}" wsgi:app
|
||||
Reference in New Issue
Block a user