mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-06 03:30:25 -06:00
- Improve web interface layout for better user-friendliness and mobile responsiveness * Update CSS variables for consistent spacing and component sizing * Enhance card layouts with improved padding, borders, and shadows * Optimize button and form element dimensions for better touch targets * Add hover effects and animations for improved user interaction * Implement responsive grid system with mobile-first approach - Refactor mobile JavaScript to prevent duplicate initialization * Consolidate mobile enhancements into dedicated utility classes * Add initialization guards to prevent double loading * Implement MobileUtils and MobileNavigation classes * Remove duplicate event listeners and mobile enhancements - Fix circular import issue in logo handling * Replace problematic 'from app import app' with Flask's current_app * Add error handling for cases where current_app is unavailable * Improve logo path resolution with fallback mechanisms * Fix settings model to use proper Flask context - Clean up template code and remove duplication * Remove duplicate mobile enhancements from base template * Clean up dashboard template JavaScript * Centralize all mobile functionality in mobile.js * Add proper error handling and debugging - Update CSS variables and spacing system * Introduce --section-spacing and --card-spacing variables * Add mobile-specific spacing variables * Improve border-radius and shadow consistency * Enhance typography and visual hierarchy This commit resolves the double loading issue and logo import errors while significantly improving the overall user experience and mobile responsiveness of the web interface.
6.8 KiB
6.8 KiB
GitHub Workflow Docker Images with Database Initialization
This guide explains how the TimeTracker Docker images built through GitHub workflows automatically handle database initialization and port exposure.
Overview
The GitHub workflows build Docker images that include:
- Automatic database connection checking
- Database initialization logic
- Port 8080 properly exposed
- Health checks and monitoring
Workflow Images
1. External Database Image (docker-publish-external.yml)
- Image:
ghcr.io/drytrix/timetracker-externaldb - Uses:
Dockerfile(copied toDockerfile.final) - Purpose: For deployments with external PostgreSQL databases
- Features:
- Waits for external database to be ready
- Checks if database is initialized
- Auto-initializes missing tables
- Port 8080 exposed
2. Internal Database Image (docker-publish-internal.yml)
- Image:
ghcr.io/drytrix/timetracker-internaldb - Uses:
Dockerfile.simple(copied toDockerfile.final) - Purpose: For all-in-one deployments with built-in PostgreSQL
- Features:
- Starts PostgreSQL internally
- Auto-initializes database
- Creates tables and default data
- Port 8080 exposed
3. Combined Image (Dockerfile.combined)
- Purpose: For complex deployments with multiple services
- Features:
- PostgreSQL + Flask app in one container
- Supervisor for process management
- Auto-database initialization
- Ports 8080 and 5432 exposed
How Database Initialization Works
Step 1: Database Connection Check
# Wait for PostgreSQL to be ready
python -c "
import os, time, sys
from sqlalchemy import create_engine, text
url = os.getenv('DATABASE_URL', '')
if url.startswith('postgresql'):
for attempt in range(30):
try:
engine = create_engine(url, pool_pre_ping=True)
with engine.connect() as conn:
conn.execute(text('SELECT 1'))
print('Database connection established successfully')
break
except Exception as e:
print(f'Waiting for database... (attempt {attempt+1}/30): {e}')
time.sleep(2)
else:
print('Database not ready after waiting, exiting...')
sys.exit(1)
"
Step 2: Initialization Check
# Check if required tables exist
python -c "
import os, sys
from sqlalchemy import create_engine, text, inspect
url = os.getenv('DATABASE_URL', '')
if url.startswith('postgresql'):
try:
engine = create_engine(url, pool_pre_ping=True)
inspector = inspect(engine)
existing_tables = inspector.get_table_names()
required_tables = ['users', 'projects', 'time_entries', 'settings']
missing_tables = [table for table in required_tables if table not in existing_tables]
if missing_tables:
print(f'Database not fully initialized. Missing tables: {missing_tables}')
sys.exit(1) # Trigger initialization
else:
print('Database is already initialized')
sys.exit(0) # Skip initialization
except Exception as e:
print(f'Error checking database: {e}')
sys.exit(1)
"
Step 3: Database Initialization
if [ $? -eq 1 ]; then
echo "Initializing database..."
python /app/docker/init-database.py
if [ $? -eq 0 ]; then
echo "Database initialized successfully"
else
echo "Database initialization failed, but continuing..."
fi
else
echo "Database already initialized, skipping initialization"
fi
Port Exposure
All images properly expose port 8080:
# Expose port
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8080/_health || exit 1
Using the Images
External Database Deployment
# docker-compose.yml
services:
app:
image: ghcr.io/drytrix/timetracker-externaldb:latest
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgresql://user:pass@host:5432/db
restart: unless-stopped
Internal Database Deployment
# docker-compose.yml
services:
app:
image: ghcr.io/drytrix/timetracker-internaldb:latest
ports:
- "8080:8080"
restart: unless-stopped
Direct Docker Run
# External database
docker run -d -p 8080:8080 \
-e DATABASE_URL="postgresql://user:pass@host:5432/db" \
ghcr.io/drytrix/timetracker-externaldb:latest
# Internal database (all-in-one)
docker run -d -p 8080:8080 \
ghcr.io/drytrix/timetracker-internaldb:latest
Environment Variables
Required for External Database
DATABASE_URL=postgresql://user:password@host:port/database
Optional for All Images
TZ=Europe/Rome
CURRENCY=EUR
ROUNDING_MINUTES=1
SINGLE_ACTIVE_TIMER=true
ALLOW_SELF_REGISTER=true
IDLE_TIMEOUT_MINUTES=30
ADMIN_USERNAMES=admin
SECRET_KEY=your-secret-key-change-this
What Happens on Startup
- Container starts with the built-in startup script
- Database connection check waits for PostgreSQL to be ready
- Initialization check verifies required tables exist
- Auto-initialization runs if needed using Python script
- Flask application starts normally
- Port 8080 is accessible from the host
Benefits
- No manual database setup required
- Automatic table creation and default data
- Port 8080 always available in Docker Desktop
- Health checks ensure application is ready
- Error handling continues even if initialization fails
- Fast startup for already-initialized databases
Troubleshooting
Port Not Visible in Docker Desktop
- Ensure you're using the built images, not building locally
- Check that the container is running:
docker ps - Verify port mapping:
docker port <container_id>
Database Initialization Issues
# Check container logs
docker logs <container_id>
# Test database manually
docker exec <container_id> python /app/docker/test-db.py
# Check database status
docker exec <container_id> python /app/docker/init-database.py
Health Check Failures
- Ensure the
/_healthendpoint is accessible - Check if the app is binding to the correct port
- Verify network connectivity
Workflow Triggers
The images are automatically built and published on:
- Push to main branch: Latest development version
- Tagged releases: Versioned releases (v1.0.0, v2.0.0, etc.)
- Manual dispatch: Manual workflow triggers
- Pull requests: Build verification (not published)
Image Tags
latest: Most recent successful buildmain: Latest main branch buildv*: Versioned releases (v1.0.0, v2.0.0, etc.)<commit-sha>: Specific commit builds
Now when you deploy these images from the GitHub Container Registry, they will automatically handle database initialization and expose port 8080 properly in Docker Desktop!