9.5 KiB
9.5 KiB
Database Setup for Docker Deployment
Overview
The Recticel Quality Application uses a dual-database approach:
- MariaDB (Primary) - Production data, users, permissions, orders
- SQLite (Backup/Legacy) - Local user authentication fallback
Database Configuration Flow
1. Docker Environment Variables → Database Connection
Docker .env file
↓
docker-compose.yml (environment section)
↓
Docker container environment variables
↓
setup_complete_database.py (reads from env)
↓
external_server.conf file (generated)
↓
Application runtime (reads conf file)
2. Environment Variables Used
| Variable | Default | Purpose | Used By |
|---|---|---|---|
DB_HOST |
db |
Database server hostname | All DB operations |
DB_PORT |
3306 |
MariaDB port | All DB operations |
DB_NAME |
trasabilitate |
Database name | All DB operations |
DB_USER |
trasabilitate |
Database username | All DB operations |
DB_PASSWORD |
Initial01! |
Database password | All DB operations |
MYSQL_ROOT_PASSWORD |
rootpassword |
MariaDB root password | DB initialization |
INIT_DB |
true |
Run schema setup | docker-entrypoint.sh |
SEED_DB |
true |
Create superadmin user | docker-entrypoint.sh |
3. Database Initialization Process
Phase 1: MariaDB Container Startup
# docker-compose.yml starts MariaDB container
# init-db.sql runs automatically:
1. CREATE DATABASE trasabilitate
2. CREATE USER 'trasabilitate'@'%'
3. GRANT ALL PRIVILEGES
Phase 2: Application Container Waits
# docker-entrypoint.sh:
1. Waits for MariaDB to be ready (health check)
2. Tests connection with credentials
3. Retries up to 60 times (2s intervals = 120s timeout)
Phase 3: Configuration File Generation
# docker-entrypoint.sh creates:
/app/instance/external_server.conf
server_domain=db # From DB_HOST
port=3306 # From DB_PORT
database_name=trasabilitate # From DB_NAME
username=trasabilitate # From DB_USER
password=Initial01! # From DB_PASSWORD
Phase 4: Schema Creation (if INIT_DB=true)
# setup_complete_database.py creates:
- scan1_orders (quality scans - station 1)
- scanfg_orders (quality scans - finished goods)
- order_for_labels (production orders for labels)
- warehouse_locations (warehouse management)
- users (user authentication)
- roles (user roles)
- permissions (permission definitions)
- role_permissions (role-permission mappings)
- role_hierarchy (role inheritance)
- permission_audit_log (permission change tracking)
# Also creates triggers:
- increment_approved_quantity (auto-count approved items)
- increment_approved_quantity_fg (auto-count finished goods)
Phase 5: Data Seeding (if SEED_DB=true)
# seed.py creates:
- Superadmin user (username: superadmin, password: superadmin123)
# setup_complete_database.py also creates:
- Default permission set (35+ permissions)
- Role hierarchy (7 roles: superadmin → admin → manager → workers)
- Role-permission mappings
4. How Application Connects to Database
A. Settings Module (app/settings.py)
def get_external_db_connection():
# Reads /app/instance/external_server.conf
# Returns mariadb.connect() using conf values
B. Other Modules (order_labels.py, print_module.py, warehouse.py)
def get_db_connection():
# Also reads external_server.conf
# Each module manages its own connections
C. SQLAlchemy (app/init.py)
# Currently hardcoded to SQLite (NOT DOCKER-FRIENDLY!)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
Current Issues & Recommendations
❌ Problem 1: Hardcoded SQLite in init.py
Issue: app/__init__.py uses hardcoded SQLite connection
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
Impact:
- Not using environment variables
- SQLAlchemy not connected to MariaDB
- Inconsistent with external_server.conf approach
Solution: Update to read from environment:
import os
def create_app():
app = Flask(__name__)
# Database configuration from environment
db_user = os.getenv('DB_USER', 'trasabilitate')
db_pass = os.getenv('DB_PASSWORD', 'Initial01!')
db_host = os.getenv('DB_HOST', 'localhost')
db_port = os.getenv('DB_PORT', '3306')
db_name = os.getenv('DB_NAME', 'trasabilitate')
# Use MariaDB/MySQL connection
app.config['SQLALCHEMY_DATABASE_URI'] = (
f'mysql+mariadb://{db_user}:{db_pass}@{db_host}:{db_port}/{db_name}'
)
❌ Problem 2: Dual Connection Methods
Issue: Application uses two different connection methods:
- SQLAlchemy ORM (for User model)
- Direct mariadb.connect() (for everything else)
Impact:
- Complexity in maintenance
- Potential connection pool exhaustion
- Inconsistent transaction handling
Recommendation: Standardize on one approach:
- Option A: Use SQLAlchemy for everything (preferred)
- Option B: Use direct mariadb connections everywhere
❌ Problem 3: external_server.conf Redundancy
Issue: Configuration is duplicated:
- Environment variables → external_server.conf
- Application reads external_server.conf
Impact:
- Unnecessary file I/O
- Potential sync issues
- Not 12-factor app compliant
Recommendation: Read directly from environment variables
Docker Deployment Database Schema
MariaDB Container Configuration
# docker-compose.yml
db:
image: mariadb:11.3
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: trasabilitate
MYSQL_USER: trasabilitate
MYSQL_PASSWORD: Initial01!
volumes:
- /srv/docker-test/mariadb:/var/lib/mysql # Persistent storage
- ./init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
Database Tables Created
| Table | Purpose | Records |
|---|---|---|
scan1_orders |
Quality scan records (station 1) | 1000s |
scanfg_orders |
Finished goods scan records | 1000s |
order_for_labels |
Production orders needing labels | 100s |
warehouse_locations |
Warehouse location codes | 50-200 |
users |
User accounts | 10-50 |
roles |
Role definitions | 7 |
permissions |
Permission definitions | 35+ |
role_permissions |
Role-permission mappings | 100+ |
role_hierarchy |
Role inheritance tree | 7 |
permission_audit_log |
Permission change audit trail | Growing |
Default Users & Roles
Superadmin User:
- Username:
superadmin - Password:
superadmin123 - Role:
superadmin - Access: Full system access
Role Hierarchy:
superadmin (level 1)
└─ admin (level 2)
└─ manager (level 3)
├─ quality_manager (level 4)
│ └─ quality_worker (level 5)
└─ warehouse_manager (level 4)
└─ warehouse_worker (level 5)
Production Deployment Checklist
- Change
MYSQL_ROOT_PASSWORDfrom default - Change
DB_PASSWORDfrom default (Initial01!) - Change superadmin password from default (superadmin123)
- Set
INIT_DB=falseafter first deployment - Set
SEED_DB=falseafter first deployment - Set strong
SECRET_KEYin environment - Backup MariaDB data directory regularly
- Enable MariaDB binary logging for point-in-time recovery
- Configure proper
DB_MAX_RETRIESandDB_RETRY_INTERVAL - Monitor database connections and performance
- Set up database user with minimal required privileges
Troubleshooting
Database Connection Failed
# Check if MariaDB container is running
docker-compose ps
# Check MariaDB logs
docker-compose logs db
# Test connection from app container
docker-compose exec web python3 -c "
import mariadb
conn = mariadb.connect(
user='trasabilitate',
password='Initial01!',
host='db',
port=3306,
database='trasabilitate'
)
print('Connection successful!')
"
Tables Not Created
# Run setup script manually
docker-compose exec web python3 /app/app/db_create_scripts/setup_complete_database.py
# Check tables
docker-compose exec db mysql -utrasabilitate -pInitial01! trasabilitate -e "SHOW TABLES;"
external_server.conf Not Found
# Verify file exists
docker-compose exec web cat /app/instance/external_server.conf
# Recreate if missing (entrypoint should do this automatically)
docker-compose restart web
Migration from Non-Docker to Docker
If migrating from a non-Docker deployment:
-
Backup existing MariaDB database:
mysqldump -u trasabilitate -p trasabilitate > backup.sql -
Update docker-compose.yml paths to existing data:
db: volumes: - /path/to/existing/mariadb:/var/lib/mysql -
Or restore to new Docker MariaDB:
docker-compose exec -T db mysql -utrasabilitate -pInitial01! trasabilitate < backup.sql -
Verify data:
docker-compose exec db mysql -utrasabilitate -pInitial01! trasabilitate -e "SELECT COUNT(*) FROM users;"
Environment Variable Examples
Development (.env)
DB_HOST=db
DB_PORT=3306
DB_NAME=trasabilitate
DB_USER=trasabilitate
DB_PASSWORD=Initial01!
MYSQL_ROOT_PASSWORD=rootpassword
INIT_DB=true
SEED_DB=true
FLASK_ENV=development
GUNICORN_LOG_LEVEL=debug
Production (.env)
DB_HOST=db
DB_PORT=3306
DB_NAME=trasabilitate
DB_USER=trasabilitate
DB_PASSWORD=SuperSecurePassword123!@#
MYSQL_ROOT_PASSWORD=SuperSecureRootPass456!@#
INIT_DB=false
SEED_DB=false
FLASK_ENV=production
GUNICORN_LOG_LEVEL=info
SECRET_KEY=your-super-secret-key-change-this