Python Basic Webserver with Database
Flask server that connects to PostgreSQL and reads from a tasks table
A minimal Flask web server that connects to a PostgreSQL database and reads from a tasks table. Demonstrates the full producer/consumer flow — UIS deploys PostgreSQL, dev-template configure creates the database and wires the connection into .env, and the app reads from it. Includes Docker containerization, Kubernetes deployment manifests, and GitHub Actions CI/CD workflow. Consumer-side companion to the postgresql-demo UIS stack template.
terchrisPrerequisites
- DCT devcontainer running
- UIS provision-host container running
- Local Kubernetes cluster running (Rancher Desktop)
Files
Files (10)
├── .gitignore ├── Dockerfile ├── README-python-basic-webserver-database.md ├── requirements.txt ├── template-info.yaml ├── .github/ │ └── workflows/ │ └── urbalurba-build-and-push.yaml ├── app/ │ └── app.py ├── config/ │ └── init-database.sql └── manifests/ ├── deployment.yaml └── kustomization.yaml
Related templates
①What gets set up
When you install this template, the following are configured for you:
- Adds ipython, pytest-cov, uv, and VS Code extensions for Python development
- Open-source relational database
- Databasemy_app_db
- Usermy_app
- K8s Secretmy-app-db
- Port-forwardhost.docker.internal:35432
- Env varDATABASE_URL
- Namespacedefault
- Helm chartbitnami/postgresql
config/init-database.sql
-- Init file for python-basic-webserver-database
-- Applied by: uis configure postgresql --init-file -
-- Uses psql --set ON_ERROR_STOP=on for fail-fast on syntax errors
-- All statements are idempotent — safe to re-run
CREATE TABLE IF NOT EXISTS tasks (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
INSERT INTO tasks (title, status) VALUES
('Set up the database connection', 'done'),
('Build something with Flask + PostgreSQL', 'pending'),
('Deploy to Kubernetes via ArgoCD', 'pending')
ON CONFLICT DO NOTHING;
②Configure
Set up and configure the backend services this template needs. Creates a per-app database, wires credentials into a local .env file, and stores a Kubernetes Secret in your cluster for the deployed pod.
Uses: PostgreSQLtemplate-info.yaml — edit to change defaultsid: python-basic-webserver-database
version: "1.0.0"
name: Python Basic Webserver with Database
description: Flask server that connects to PostgreSQL and reads from a tasks table
category: BASIC_WEB_SERVER_DATABASE
install_type: app
abstract: >
A minimal Flask web server that connects to a PostgreSQL database and
reads from a tasks table. Demonstrates the full producer/consumer
flow — UIS deploys PostgreSQL, dev-template configure creates the
database and wires the connection into .env, and the app reads from
it. Includes Docker containerization, Kubernetes deployment manifests,
and GitHub Actions CI/CD workflow. Consumer-side companion to the
postgresql-demo UIS stack template.
tools: dev-python
readme: README-python-basic-webserver-database.md
tags:
- python
- flask
- postgresql
- database
- webserver
- requires
logo: python-basic-webserver-database-logo.svg
maintainers:
- terchris
links:
- url: https://github.com/helpers-no/dev-templates/tree/main/templates/python-basic-webserver-database
title: Source code
icon: github
related:
- python-basic-webserver
- postgresql-demo
quickstart:
title: "Run the Flask app"
setup:
- uv venv
- uv pip install -r requirements.txt
run: "uv run python app/app.py"
note: |
Flask debug server starts on port 3000.
VS Code auto-forwards the port — click the globe icon in the Ports tab.
# Command a developer runs to provision the backend services this template
# needs. Read by the Environment card and the architecture diagram builder.
# App templates use `dev-template configure`; stack templates use the
# `uis template install` form; templates with no configure step omit this.
configure_command: "dev-template configure"
params:
app_name: "my-app"
database_name: "my_app_db"
prerequisites:
- text: "DCT devcontainer running"
url: "https://dct.sovereignsky.no"
- text: "UIS provision-host container running"
url: "https://uis.sovereignsky.no"
- text: "Local Kubernetes cluster running (Rancher Desktop)"
url: "https://www.rancher.com/products/rancher-desktop"
requires:
- service: postgresql
config:
database: "{{ params.database_name }}"
init: "config/init-database.sql"
Then run:
dev-template configureExpected output from dev-template configure
🔧 Template Configure
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔌 Checking UIS bridge...
✓ uis-provision-host container is running
🔍 Detecting git identity...
✓ Repo: yourorg/my-app
✓ Branch: main
📄 Reading template-info.yaml...
✓ File: /workspace/template-info.yaml
✓ ID: python-basic-webserver-database
✓ Type: app
📝 Parameters:
app_name = my-app
database_name = my_app_db
🔧 Configuring 1 service requirement...
─── postgresql ──────────────────────────────────────────────────
Database: my_app_db
K8s namespace: default
K8s secret prefix: my-app
Env var: DATABASE_URL
📄 Reading init file...
✓ Path: config/init-database.sql
✓ Size: 702 bytes (19 lines)
📡 Calling UIS (you can copy-paste this to debug):
docker exec -i uis-provision-host uis configure postgresql my-app \
--database my_app_db \
--namespace default \
--secret-name-prefix my-app \
--init-file - \
--json \
< config/init-database.sql
Waiting for UIS response...
✓ Status: ok (took 2s)
📦 UIS created:
Database: my_app_db
Username: my_app
Password: *** (hidden)
🔌 Port forward (created by UIS, lives inside uis-provision-host):
┌─────────────────────────────────────────────────┐
│ DCT → host.docker.internal:35432 │ ← your app connects here
└─────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────┐
│ Mac/Linux host → port 35432 │ ← Docker port-publish
└─────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────┐
│ uis-provision-host container → port 35432 │ ← kubectl port-forward
└─────────────────────────────────────────────────┘ lives inside this container
↕
┌─────────────────────────────────────────────────┐
│ K8s: postgresql.default.svc.cluster.local:5432 │ ← actual postgresql pod
└─────────────────────────────────────────────────┘
Survives DCT rebuilds. Dies if you restart uis-provision-host.
Manage: uis expose --status (list all forwards)
uis expose postgresql --stop (tear down this one)
💾 Writing local URL to .env...
✓ File: /workspace/.env
✓ Key: DATABASE_URL
✓ Value: postgresql://my_app:***@host.docker.internal:35432/my_app_db
🔐 K8s Secret (created by UIS for ArgoCD/in-cluster pods):
Name: my-app-db
Namespace: my-app
Key: DATABASE_URL
Verify: kubectl get secret my-app-db -n my-app
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Configuration complete (1 configured, 0 skipped, 0 failed)
Total time: 2s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 Next steps:
• Verify the database: uis connect postgresql my_app_db
• Check the K8s secret: kubectl get secret my-app-db -n my-app
• Check port forwards: uis expose --status
• Run the app: uv run python app/app.py③Setup
uv venv
uv pip install -r requirements.txt④Run the Flask app
uv run python app/app.pyFlask debug server starts on port 3000. VS Code auto-forwards the port — click the globe icon in the Ports tab.
Architecture
These diagrams are auto-generated from the template's metadata. Click any diagram to enlarge.
Local development
Components
Deployment
Components
Template README
The Python Basic Webserver with Database template is a Flask app that connects to PostgreSQL and reads from a tasks table. The purpose of this app is to verify that both the development environment and the database connection are set up and working. See more documentation at http://localhost:3000/docs/templates/basic-web-server-database/python-basic-webserver-database
Configuration and database URL
DATABASE_URLmust be set (typically via.envafterdev-template configure). If it is missing, the process exits with an error — there is no default connection string.- Connections use
psycopg2viaget_connection()inapp/app.py.
Schema and seed data
config/init-database.sqldefines the defaulttaskstable, indexes, and seed rows. UIS applies this when you rundev-template configure(see the docs page for the full flow).- Change the schema in that file, then run
dev-template configureagain so the database matches.
HTTP API
| Path | Method | Response |
|---|---|---|
/ | GET | HTML greeting with template name, time, and links to /tasks and /health |
/tasks | GET | JSON array of tasks rows (id, title, status, created_at), or 500 with {"error": ...} on query failure |
/health | GET | {"status": "ok", "database": "connected"} when the DB answers SELECT 1; 503 with {"status": "error", "database": ...} if the connection fails |
Entry point and dev server
- File:
app/app.py - Port: 3000 (constant in code; align with Dockerfile/manifests if you change it)
- Run:
uv run python app/app.py(or activate a venv and runpython app/app.py). Flask debug mode is enabled inif __name__ == '__main__'.
Changing the app
- Add routes and helpers in
app/app.py. Reuseget_connection()for DB access. - If you rename tables or columns, update
config/init-database.sqland re-rundev-template configure, and keep/tasksin sync with your queries.