e0b9e27b90
- New api/ Python service (stdlib only — no pip install, no packages): validates fields server-side, verifies reCAPTCHA, sends via Resend with idempotency key, rate-limited (5 req/IP/15min) - Matches existing project tooling (build_locations.py, build_services.py) - Front-end form.js stays vanilla JS, no JS frameworks anywhere - docker-compose runs nginx + python:3.13-alpine api with healthcheck - nginx proxies /api/ to Python service, strips prefix - Dockerfile now copies only public folders into web root (was copying everything, exposing /Dockerfile, /build_*.py, /api/.env) - nginx.conf denies dotfiles, .env, .conf, .yml, .py, .md, .txt and Dockerfile as defense in depth - .dockerignore keeps sensitive files out of build context - .gitignore protects api/.env and __pycache__ from being committed
28 lines
657 B
YAML
28 lines
657 B
YAML
services:
|
|
web:
|
|
image: floorithardwoodfloors-static
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
ports:
|
|
- "8096:80"
|
|
depends_on:
|
|
api:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
api:
|
|
image: floorithardwoodfloors-api
|
|
build:
|
|
context: ./api
|
|
dockerfile: Dockerfile
|
|
env_file: ./api/.env
|
|
expose:
|
|
- "3001"
|
|
healthcheck:
|
|
test: ["CMD", "python3", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://localhost:3001/health',timeout=3).status==200 else 1)"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|