Clean up and organize the flask-shopdb repository for better maintainability and discoverability: ## Changes - Update .gitignore for build artifacts (publish/, data/, 122M total) - Reorganize .claude/ into 6 subdirectories with README navigation - Consolidate overlapping MCP setup guides into MCP-QUICK-START.md - Move deployment docs from root to docs/deployment/ - Archive dated status reports to .claude/archived/ - Delete temporary files (logs, backups, empty reports, ~50K) ## New Structure .claude/ organized into: - setup/ - MCP, VM, Hyper-V, GitHub setup guides + scripts (17 files) - plans/ - Feature plans and protocols (5 files) - maintenance/ - Deployment checklists and reports (4 files) - archived/ - Historical documentation (9 files) - skills/ - Claude Code automation (5 files) - workflows/ - Security audit workflow (1 file) docs/deployment/ created with 6 deployment guides: - LOCAL-DEV-SETUP.md, DOCKER-SETUP.md, DOCKER-PREBUILT-APPROACH.md - PRODUCTION-READINESS.md, DEPLOY-TO-VM.md, README.md Root directory cleaned to essential docs only: - CLAUDE.md, README.md, CONTRIBUTING.md, CHANGELOG.md Benefits: - Clear navigation via README.md in each subdirectory - No duplicate/overlapping documentation - Large artifacts properly gitignored (won't bloat repository) - Historical context preserved in archived/ See .claude/CLEANUP-SUMMARY.md for complete details. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
10 KiB
ShopDB Docker Setup
Complete Docker deployment for development and testing.
Prerequisites
- Docker Desktop installed and running
- At least 8GB RAM allocated to Docker
- Zscaler corporate certificate extracted (if behind corporate proxy)
Quick Start
# 1. Clone repository
cd C:/Users/YOUR_USERNAME/Documents/github/flask-shopdb
# 2. Extract Zscaler certificate (if needed)
powershell.exe -File C:/temp/extract-ca.ps1
# This creates corp-root-ca.pem in repo root
# 3. Build images
docker compose build
# 4. Start stack
docker compose up -d
# 5. Initialize database (first time only)
docker compose exec api flask db upgrade
# 6. Install plugins (first time only)
docker compose exec api flask plugin apply-profile deploy/site-profile-universal.json
# 7. Access ShopDB
https://localhost:5001
Login: admin / (reset password - see below)
Architecture
The Docker stack includes:
-
MySQL Database (
dbservice)- Port: 3306 (internal), mapped to host based on
.env - Volume:
db_datafor persistence - Health checks enabled
- Port: 3306 (internal), mapped to host based on
-
Flask API (
apiservice)- Port: 5001 (HTTPS with self-signed cert)
- Built frontend served from
/app/frontend/dist - Gunicorn with gevent workers (4 workers, 2000 connections each)
- Volumes:
instance_data- Plugin state, uploads, branding./plugins- Plugin code (read-only)./scripts- Deployment scripts (read-only)./certs- TLS certificates (read-only)
-
Backup Service (optional, via
docker-compose.backup.yml)- One-shot container for backups
- Triggered manually or via scheduler
First-Time Setup
1. Extract Zscaler Certificate (Corporate Proxy)
Save this as C:/temp/extract-ca.ps1:
$request = [System.Net.HttpWebRequest]::Create('https://registry.npmjs.org/')
$request.Method = 'HEAD'
$request.Timeout = 10000
$response = $request.GetResponse()
$root = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($request.ServicePoint.Certificate)
$builder = [System.Text.StringBuilder]::new()
[void]$builder.AppendLine('-----BEGIN CERTIFICATE-----')
[void]$builder.AppendLine([System.Convert]::ToBase64String($root.RawData, 'InsertLineBreaks'))
[void]$builder.AppendLine('-----END CERTIFICATE-----')
$certPath = 'C:\Users\270015376\Documents\github\flask-shopdb\corp-root-ca.pem'
Set-Content -Path $certPath -Value $builder.ToString() -Encoding ASCII
Write-Host "Staged corp-root-ca.pem"
Run: powershell.exe -ExecutionPolicy Bypass -File C:/temp/extract-ca.ps1
2. Generate TLS Certificates
cd certs
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout server.key -out server.crt -days 365 \
-subj "//CN=localhost"
Or use the provided script:
./scripts/generate-dev-certs.sh
3. Configure Environment
Copy and edit .env:
cp .env.docker-dev .env
# Edit if needed - defaults work for local dev
4. Build Images
docker compose build
Note: First build takes 10-15 minutes due to:
- npm install (~5 min with Zscaler proxy)
- Frontend Vite build (~2 min)
- Python dependencies (~3 min)
Subsequent builds use Docker layer cache and are much faster.
5. Start Services
docker compose up -d
Check status:
docker compose ps
docker compose logs -f api
6. Initialize Database
# Run migrations
docker compose exec api flask db upgrade
# Install and enable all plugins
docker compose exec api flask plugin apply-profile deploy/site-profile-universal.json
The apply-profile command:
- Installs all 17 plugins
- Registers them in
instance/plugins.json - Leaves them disabled by default
- Enables them via Settings UI as needed
7. Reset Admin Password
# Generate hash for "admin" password
docker compose exec api python -c "from werkzeug.security import generate_password_hash; print(generate_password_hash('admin'))"
# Update database
docker compose exec db mysql -u root -p shopdb_flask -e "
UPDATE users
SET passwordhash = 'PASTE_HASH_HERE',
failedlogins = 0,
lockeduntil = NULL
WHERE username = 'admin';"
Or use quick method (sets password to admin):
docker compose exec db mysql -u root -p shopdb_flask -e "
UPDATE users SET
passwordhash = 'scrypt:32768:8:1\$B4LhpPrM6qxijInK\$b99b47a0bb5fd45761a1823f401f70a3ceccf71a5d38dc433378aa07426ef8eaf7e679ff3dd7b0ce9772600f83368ac642e9419b9beaa49f87483318bae34547',
failedlogins = 0,
lockeduntil = NULL
WHERE username = 'admin';"
Import Production Database
# Copy SQL dump to container
docker cp latest.sql shopdb-api-1:/tmp/
# Import
docker compose exec db mysql -u root -p shopdb_flask < /tmp/latest.sql
# Run migrations to bring schema up to date
docker compose exec api flask db upgrade
docker compose exec api flask plugin upgrade-all
Common Commands
View Logs
docker compose logs -f api
docker compose logs -f db
Restart Services
docker compose restart api
docker compose down && docker compose up -d
Rebuild After Code Changes
docker compose build api
docker compose up -d api
Access Container Shell
docker compose exec api bash
docker compose exec db bash
Run Flask Commands
docker compose exec api flask plugin list
docker compose exec api flask db current
docker compose exec api flask routes
Backup & Restore
# Trigger backup
docker compose -f docker-compose.backup.yml up backup
# View backups
docker compose exec api flask plugin list
# (Accessible via Settings > Backups in UI)
# Restore (via UI at Settings > Backups > Select backup > Restore)
Troubleshooting
"npm ci failed" during build
Cause: Zscaler proxy blocking npm registry.
Fix:
- Extract Zscaler certificate (see above)
- Ensure
corp-root-ca.pemexists in repo root - Rebuild:
docker compose build --no-cache
"database is unhealthy"
Cause: MySQL container not ready or port conflict.
Fix:
# Check logs
docker compose logs db
# Check if port 3306 is already in use
netstat -an | grep 3306
# If conflict, edit .env and set MYSQL_PORT=3307
"Access denied for user 'shopdb'"
Cause: Database credentials mismatch.
Fix: Check .env file - MYSQL_PASSWORD must match DATABASE_URL.
"Could not connect to database"
Cause: Database service not started or wrong hostname.
Fix:
# Check db is running
docker compose ps
# API must use hostname 'db' not 'localhost'
# In docker-compose.yml: DATABASE_URL=...@db:3306/...
"ERR_CERT_AUTHORITY_INVALID" in browser
Expected: Self-signed certificate warning.
Fix: Click "Advanced" > "Proceed to localhost (unsafe)" - this is normal for dev.
Or generate proper cert:
# Add your machine's hostname to cert
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout certs/server.key -out certs/server.crt -days 365 \
-subj "//CN=$(hostname)" \
-addext "subjectAltName=DNS:localhost,DNS:$(hostname),IP:127.0.0.1"
"Plugin X is already installed" but not visible
Cause: Plugin installed but not enabled.
Fix:
docker compose exec api flask plugin enable X
docker compose restart api
Build is very slow
Expected: First build with Zscaler proxy takes 10-15 minutes.
Speed up:
- Subsequent builds use cache (much faster)
- If rebuilding often, comment out
--no-cacheflag - Build frontend separately on host, copy dist/ into image
Production Deployment Notes
For production:
-
Change all secrets in
.env:SECRET_KEYJWT_SECRET_KEYMYSQL_ROOT_PASSWORDMYSQL_PASSWORD
-
Use proper TLS certificates (not self-signed):
- Place in
./certs/server.crtand./certs/server.key - Or use reverse proxy (nginx/IIS) for TLS termination
- Place in
-
Set
FLASK_DEBUG=0in production -
Configure backups:
- Set up cron job:
0 2 * * * cd /path/to/shopdb && docker compose -f docker-compose.backup.yml up backup - Configure SMB or S3 destination in Settings > Backups
- Set up cron job:
-
Set
SHOPDB_ENV_LABELto site name (e.g., "WEST-JEFFERSON") -
Review
docker-compose.yml:- Adjust worker count based on load
- Configure proper
restartpolicy - Set resource limits if needed
Architecture Notes
Why HTTPS in Docker?
Secure context APIs (clipboard, geolocation) require HTTPS. Running over HTTP disables these browser features.
Why Gevent Workers?
Endpoint agents long-poll /api/endpoints/commands/next. With threading, 200 agents = 200 threads = resource exhaustion. Gevent uses greenlets (cheap coroutines) so 2000+ connections per worker is feasible.
Plugin Bootstrap
The entrypoint (scripts/docker-entrypoint.sh) automatically:
- Runs database migrations
- Checks if
instance/plugins.jsonexists - If not, installs all available plugins (disabled)
- Starts gunicorn
This ensures imported databases with plugin tables get matching plugin registry.
Instance Data Persistence
The instance_data volume persists:
plugins.json- Which plugins are enabled- Uploaded files (floor plans, branding, photos, warranties, slides)
- Dell OAuth tokens
- Any plugin-specific state
Important: docker compose down -v deletes volumes - use plain docker compose down to preserve data.
File Structure
flask-shopdb/
|-- docker-compose.yml # Main stack definition
|-- docker-compose.backup.yml # Backup service
|-- Dockerfile # Multi-stage build
|-- .env # Environment config (gitignored)
|-- corp-root-ca.pem # Zscaler cert (gitignored)
|-- certs/ # TLS certificates (gitignored)
| |-- server.crt
| +-- server.key
|-- scripts/
| |-- docker-entrypoint.sh # Container startup
| +-- bootstrap-plugins.sh # Plugin auto-install
+-- deploy/
+-- site-profile-universal.json # Full plugin list
Next Steps
After setup:
- Browse to https://localhost:5001
- Login as
admin - Go to Settings > Plugins
- Enable plugins your site needs
- Configure settings (CORS, backup destination, etc.)
- Import data or start fresh
For local development with hot-reload, see LOCAL-DEV-SETUP.md.