Style check fixes:
- Replace unicode box-drawing characters with ASCII (|-- instead of ├──)
- Replace emoji status markers with [OK]/[FAIL]/[WARN] tags
- Replace arrows (→ with ->, ↔ with <->) and em-dashes (— with --)
- Add venv-quick to excluded directories in check script
- Exclude darkwing report files (findings.sarif, report.md)
Backup finalization fix:
- Fix finalize-restore endpoint to not claim the upgrade sentinel
- Endpoint now checks for pending upgrade and returns {queued: true}
- Leaves UPGRADE_SENTINEL for background watcher to claim and process
- Prevents inline Alembic runs that can outlast request timeout
Claude Code context:
- Add .claude/ directory with INDEX.md and QUICK-REFERENCE.md
- Add CLAUDE.md with project overview and conventions
- Helps Claude Code understand project structure and rules
Fixes failing test: test_the_endpoint_does_not_run_the_upgrade_itself
Fixes naming/style CI check violations
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
236 lines
6.7 KiB
Markdown
236 lines
6.7 KiB
Markdown
# Docker Deployment - Complete and Working
|
|
|
|
**Date:** 2026-09-07
|
|
**Branch:** wj (post-wilm merge)
|
|
**Status:** [OK] Core system operational, backup watcher pending
|
|
|
|
## What's Running
|
|
|
|
```
|
|
CONTAINER STATUS PORT
|
|
flask-shopdb-db-1 Up (healthy) 3306/tcp (internal)
|
|
flask-shopdb-api-1 Up https://localhost:5001
|
|
```
|
|
|
|
**Gunicorn Workers:** 4 workers with gevent (PIDs 74-77)
|
|
**Plugins Enabled:** 12 of 17 installed
|
|
**Database:** MySQL 8.4 with all migrations applied
|
|
|
|
## Access
|
|
|
|
**URL:** https://localhost:5001
|
|
**Expected:** Browser warning for self-signed certificate (click through)
|
|
**Login:** admin / (needs password reset - see below)
|
|
|
|
## How to Use
|
|
|
|
### Start Stack
|
|
```bash
|
|
docker compose -f docker-compose.prebuilt.yml up -d
|
|
```
|
|
|
|
### Stop Stack
|
|
```bash
|
|
docker compose -f docker-compose.prebuilt.yml down
|
|
```
|
|
|
|
### View Logs
|
|
```bash
|
|
docker logs -f flask-shopdb-api-1
|
|
docker logs flask-shopdb-db-1
|
|
```
|
|
|
|
### Reset Admin Password
|
|
```bash
|
|
# Generate hash
|
|
docker exec flask-shopdb-api-1 python -c \
|
|
"from werkzeug.security import generate_password_hash; print(generate_password_hash('your-password'))"
|
|
|
|
# Update database (replace HASH with output above)
|
|
docker exec flask-shopdb-db-1 mysql -uroot -p$MYSQL_ROOT_PASSWORD shopdb_flask -e \
|
|
"UPDATE users SET passwordhash='HASH', failedlogins=0, lockeduntil=NULL WHERE username='admin';"
|
|
```
|
|
|
|
Quick reset to password "admin":
|
|
```bash
|
|
docker exec flask-shopdb-db-1 mysql -uroot -proot-dev-password-not-for-production shopdb_flask -e \
|
|
"UPDATE users SET
|
|
passwordhash='scrypt:32768:8:1\$B4LhpPrM6qxijInK\$b99b47a0bb5fd45761a1823f401f70a3ceccf71a5d38dc433378aa07426ef8eaf7e679ff3dd7b0ce9772600f83368ac642e9419b9beaa49f87483318bae34547',
|
|
failedlogins=0, lockeduntil=NULL
|
|
WHERE username='admin';"
|
|
```
|
|
|
|
### Rebuild After Code Changes
|
|
```bash
|
|
# Rebuild frontend (if frontend code changed)
|
|
cd frontend
|
|
npm run build
|
|
cd ..
|
|
|
|
# Rebuild Docker image
|
|
docker compose -f docker-compose.prebuilt.yml build api
|
|
|
|
# Restart
|
|
docker compose -f docker-compose.prebuilt.yml up -d
|
|
```
|
|
|
|
### Run Database Migrations
|
|
```bash
|
|
docker exec flask-shopdb-api-1 flask db upgrade
|
|
```
|
|
|
|
### Plugin Management
|
|
```bash
|
|
# List plugins
|
|
docker exec flask-shopdb-api-1 flask plugin list
|
|
|
|
# Enable plugin
|
|
docker exec flask-shopdb-api-1 flask plugin enable PLUGIN_NAME
|
|
|
|
# Disable plugin
|
|
docker exec flask-shopdb-api-1 flask plugin disable PLUGIN_NAME
|
|
```
|
|
|
|
## Build Process Used
|
|
|
|
### Why Pre-Built Frontend?
|
|
|
|
**Problem:** Zscaler corporate proxy causes npm to fail inside Docker builds
|
|
|
|
**Solution:** Build frontend on host, copy into Docker image
|
|
|
|
### Build Steps Taken
|
|
|
|
1. **Build Frontend on Host**
|
|
```bash
|
|
cd frontend
|
|
npm ci
|
|
npm run build
|
|
# Creates frontend/dist/
|
|
```
|
|
|
|
2. **Build Docker Image (Simple)**
|
|
```bash
|
|
# Uses Dockerfile.prebuilt (Python only, no npm)
|
|
docker compose -f docker-compose.prebuilt.yml build
|
|
```
|
|
|
|
3. **Start Services**
|
|
```bash
|
|
docker compose -f docker-compose.prebuilt.yml up -d
|
|
```
|
|
|
|
4. **Auto-Bootstrap**
|
|
- Container entrypoint runs migrations
|
|
- Detects first deployment (no instance/plugins.json)
|
|
- Auto-installs all 17 plugins (disabled by default)
|
|
- Starts gunicorn
|
|
|
|
## Architecture
|
|
|
|
### Volumes
|
|
- `flask-shopdb_db_data` - MySQL database (persistent)
|
|
- `flask-shopdb_instance_data` - Plugin state, uploads, branding (persistent)
|
|
|
|
### Networks
|
|
- `flask-shopdb_default` - Internal bridge network
|
|
|
|
### Image
|
|
- **Built:** 2026-09-07 00:26:27 EDT
|
|
- **Size:** 914MB
|
|
- **Base:** python:3.14-slim
|
|
- **Frontend:** Pre-built Vue 3 SPA (from host)
|
|
|
|
## What's Not Working Yet
|
|
|
|
### Backup Watcher Service
|
|
|
|
**Status:** [FAIL] Build failed
|
|
**Reason:** Oracle Linux base image can't download packages due to SSL cert issues with Zscaler
|
|
**Impact:** Can't auto-execute backups on schedule (manual backups still work via one-shot container)
|
|
|
|
**Error:**
|
|
```
|
|
Cannot download repomd.xml: Curl error (60): SSL peer certificate or SSH remote key was not OK
|
|
```
|
|
|
|
**Workaround Attempted:**
|
|
- Copied Zscaler cert to scripts/backup/zscaler-root-ca.pem
|
|
- Dockerfile.backup copies cert and runs update-ca-trust
|
|
- Still fails because microdnf runs BEFORE cert is trusted
|
|
|
|
**Fix Needed:**
|
|
- Pre-download restic binary and bake into image OR
|
|
- Use different base image (Alpine/Debian instead of Oracle Linux) OR
|
|
- Skip backup watcher entirely, use cron on host to trigger one-shot backup container
|
|
|
|
## Production Readiness
|
|
|
|
**Core Application:** [OK] Production ready
|
|
**Deployment Process:** [WARN] Requires npm on host + Docker build
|
|
**Backup System:** [FAIL] Not complete (watcher service build fails)
|
|
|
|
### Recommended Next Steps
|
|
|
|
1. **CI/CD Pipeline** - Build images automatically, push to registry
|
|
2. **Pre-Built Images** - Sites pull instead of building (2 min deploy)
|
|
3. **Backup Watcher Fix** - Switch to Alpine base or pre-download restic
|
|
4. **TLS Certificates** - Use proper certs from CA (not self-signed)
|
|
5. **Secrets Management** - Externalize passwords (.env with strong values)
|
|
|
|
## Files Created
|
|
|
|
- `Dockerfile.prebuilt` - Simplified Docker build (no npm)
|
|
- `docker-compose.prebuilt.yml` - Docker Compose for pre-built approach
|
|
- `.dockerignore.prebuilt` - Allows frontend/dist to be copied
|
|
- `start-docker-quick.sh` - Quick restart script
|
|
- `DOCKER-PREBUILT-APPROACH.md` - Documents workaround
|
|
- `PRODUCTION-READINESS.md` - Honest assessment
|
|
|
|
## Comparison to Previous Attempts
|
|
|
|
| Approach | Result | Time | Issue |
|
|
|----------|--------|------|-------|
|
|
| Multi-stage Dockerfile | [FAIL] Failed | 15+ min | npm fails with Zscaler |
|
|
| Pre-built frontend | [OK] Success | 3 min | Works! |
|
|
| Backup containers | [FAIL] Failed | N/A | Oracle Linux SSL issues |
|
|
|
|
## Verification
|
|
|
|
```bash
|
|
# Test frontend
|
|
curl -k https://localhost:5001/
|
|
# Should return: <!DOCTYPE html>
|
|
|
|
# Test API
|
|
curl -k https://localhost:5001/api/settings
|
|
# Should return: {"data":[...]}
|
|
|
|
# Test database
|
|
docker exec flask-shopdb-db-1 mysql -uroot -p$MYSQL_ROOT_PASSWORD \
|
|
-e "SELECT COUNT(*) FROM shopdb_flask.users;"
|
|
# Should return: count of users
|
|
|
|
# Check workers
|
|
docker logs flask-shopdb-api-1 2>&1 | grep "Booting worker"
|
|
# Should show: 4 workers with PIDs
|
|
|
|
# Check plugins
|
|
docker exec flask-shopdb-api-1 flask plugin list | grep Enabled | wc -l
|
|
# Should return: 12
|
|
```
|
|
|
|
## Summary
|
|
|
|
ShopDB Docker deployment is **operational** for core functionality:
|
|
- [OK] Database running
|
|
- [OK] API serving requests
|
|
- [OK] Frontend built and accessible
|
|
- [OK] Plugins installed and working
|
|
- [OK] HTTPS configured
|
|
- [WARN] Backup watcher needs work (but manual backups functional)
|
|
|
|
The pre-built frontend approach successfully bypasses Zscaler corporate proxy issues. Build time is 2-3 minutes (vs 15+ for failed multi-stage approach).
|
|
|
|
For production deployment, recommend setting up CI/CD to build images automatically and push to registry so sites can pull pre-built images instead of building locally.
|