Merge db-migrations: Add Flask-Migrate support and clean up old migration system

This commit is contained in:
2025-07-13 12:17:20 +02:00
parent 7140aeba41
commit 1500b2cf88
65 changed files with 2153 additions and 7881 deletions

189
DOCKER_MIGRATIONS_GUIDE.md Normal file
View File

@@ -0,0 +1,189 @@
# Flask-Migrate in Docker Deployments
## Overview
Docker containers typically don't include Git repositories, so we can't use Git commands to extract historical schemas. This guide explains how to use Flask-Migrate in Docker environments.
## Initial Setup (First Deployment)
When deploying with Flask-Migrate for the first time:
### Automatic Setup (via startup scripts)
The `startup.sh` and `startup_postgres.sh` scripts now automatically handle migration initialization:
1. **For existing databases with data:**
- Creates a baseline migration from current models
- Stamps the database as current (no changes applied)
- Ready for future migrations
2. **For empty databases:**
- Creates a baseline migration from current models
- Applies it to create all tables
- Ready for future migrations
### Manual Setup
If you need to set up manually:
```bash
# Inside your Docker container
python docker_migrate_init.py
# For existing database with tables:
flask db stamp head
# For new empty database:
flask db upgrade
```
## Creating New Migrations
After initial setup, create new migrations normally:
```bash
# 1. Make changes to your models
# 2. Generate migration
flask db migrate -m "Add user preferences"
# 3. Review the generated migration
cat migrations/versions/*.py
# 4. Apply the migration
flask db upgrade
```
## Helper Script
The `docker_migrate_init.py` script creates a `migrate.sh` helper:
```bash
# Check current migration status
./migrate.sh status
# Apply pending migrations
./migrate.sh apply
# Create new migration
./migrate.sh create "Add company settings"
# Mark database as current (existing DBs)
./migrate.sh mark-current
```
## Docker Compose Example
```yaml
version: '3.8'
services:
web:
build: .
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/timetrack
- FLASK_APP=app.py
volumes:
# Persist migrations between container restarts
- ./migrations:/app/migrations
depends_on:
- db
command: ./startup_postgres.sh
db:
image: postgres:13
environment:
- POSTGRES_DB=timetrack
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
```
## Important Notes
### 1. Migrations Directory
- The `migrations/` directory should be persisted between deployments
- Either use a volume mount or include it in your Docker image
- Don't regenerate migrations on each deployment
### 2. Environment Variables
Always set these in your Docker environment:
```bash
FLASK_APP=app.py
DATABASE_URL=your_database_url
```
### 3. Production Workflow
1. **Development**: Create and test migrations locally
2. **Commit**: Add migration files to Git
3. **Build**: Include migrations in Docker image
4. **Deploy**: Startup script applies migrations automatically
### 4. Rollback Strategy
To rollback a migration:
```bash
# Inside container
flask db downgrade # Go back one migration
flask db downgrade -2 # Go back two migrations
```
## Troubleshooting
### "No Git repository found"
This is expected in Docker. Use `docker_migrate_init.py` instead of the Git-based scripts.
### "Can't locate revision"
Your database references a migration that doesn't exist:
```bash
# Reset to current state
python docker_migrate_init.py
flask db stamp head
```
### Migration conflicts after deployment
If migrations were created in different environments:
```bash
# Merge migrations
flask db merge -m "Merge production and development"
flask db upgrade
```
## Best Practices
1. **Always test migrations** in a staging environment first
2. **Back up your database** before applying migrations in production
3. **Include migrations in your Docker image** for consistency
4. **Don't generate migrations in production** - only apply pre-tested ones
5. **Monitor the startup logs** to ensure migrations apply successfully
## Migration State in Different Scenarios
### Scenario 1: Fresh deployment, empty database
- Startup script runs `docker_migrate_init.py`
- Creates baseline migration
- Applies it to create all tables
### Scenario 2: Existing database, first Flask-Migrate setup
- Startup script runs `docker_migrate_init.py`
- Creates baseline migration matching current schema
- Stamps database as current (no changes)
### Scenario 3: Subsequent deployments with new migrations
- Startup script detects `migrations/` exists
- Runs `flask db upgrade` to apply new migrations
### Scenario 4: Container restart (no new code)
- Startup script detects `migrations/` exists
- Runs `flask db upgrade` (no-op if already current)
This approach ensures migrations work correctly in all Docker deployment scenarios!