voxblog/DATABASE_SETUP.md
Ender 36de987b5e
All checks were successful
Deploy to Production / deploy (push) Successful in 1m45s
feat: implement automatic database migrations on server startup
- Added new migrate.ts module to handle automatic database migrations using drizzle-orm
- Modified server startup to run migrations before Express initialization
- Added comprehensive documentation in AUTO_MIGRATION_SUMMARY.md explaining the implementation
- Updated DATABASE_SETUP.md to reflect automatic migration process and troubleshooting steps
- Added error handling to exit process if migrations fail during startup
- Implemented clear
2025-10-26 23:21:40 +01:00

4.7 KiB

Database Setup & Troubleshooting

Initial Setup

Migrations now run automatically! When you start the API, it will automatically run any pending database migrations.

Quick Setup

# 1. Start containers
docker-compose up -d --build

# 2. Wait for MySQL to be healthy and migrations to complete (about 30 seconds)
docker-compose logs -f api

# You should see:
# 🔄 Running database migrations...
# ✅ Database migrations completed successfully
# API server running on port 3301

# 3. Verify tables were created (optional)
docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SHOW TABLES;"

Manual Migration (if needed)

You can still run migrations manually if needed:

docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"

Expected output:

Tables_in_voxblog
__drizzle_migrations
audio_clips
posts
settings

Common Issues

1. Access Denied Error

Error: Access denied for user 'voxblog'@'172.20.0.3' (using password: YES)

Cause: MySQL container was created with old/different passwords

Solution: Reset the database volume and restart

docker-compose down -v
docker-compose up -d --build
# Wait 30 seconds for MySQL to initialize
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"

2. Tables Don't Exist

Error: Table 'voxblog.posts' doesn't exist

Cause: Migrations failed to run automatically (check API logs)

Solution: Check API logs for migration errors

docker-compose logs api | grep -i migration

# If migrations failed, restart the API
docker-compose restart api

# Or run migrations manually
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"

3. MySQL Container Not Healthy

Error: API can't connect to database

Solution: Check MySQL logs and wait for it to be healthy

docker-compose logs mysql
docker-compose ps  # Check if mysql is "healthy"

Database Schema

The application uses Drizzle ORM with MySQL. Schema is defined in:

  • apps/api/src/db/schema.ts

Tables

  1. posts - Blog posts with metadata

    • id, title, content_html, tags_text, feature_image
    • canonical_url, prompt, status
    • ghost_post_id, ghost_slug, ghost_published_at, ghost_url
    • selected_image_keys, generated_draft, image_placeholders
    • version, created_at, updated_at
  2. audio_clips - Audio recordings for posts

    • id, post_id, bucket, object_key, mime
    • transcript, duration_ms, created_at
  3. settings - Application settings

    • id, key, value, updated_at

Migrations

Location

  • Migration files: apps/api/drizzle/
  • Config: apps/api/drizzle.config.ts

Commands

# Generate new migration (after schema changes)
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:generate"

# Run migrations
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"

Environment Variables

Database connection uses these variables from .env:

# MySQL Root
MYSQL_ROOT_PASSWORD=voxblogRootPass123!

# Application User
MYSQL_PASSWORD=voxblogAppPass123!
DB_HOST=mysql
DB_PORT=3306
DB_USER=voxblog
DB_PASSWORD=voxblogAppPass123!
DB_NAME=voxblog

Important: If you change these values, you must recreate the MySQL container:

docker-compose down -v
docker-compose up -d --build

Backup & Restore

Backup

# Backup all data
docker exec voxblog-mysql mysqldump -u voxblog -pvoxblogAppPass123! voxblog > backup.sql

# Backup specific table
docker exec voxblog-mysql mysqldump -u voxblog -pvoxblogAppPass123! voxblog posts > posts_backup.sql

Restore

# Restore from backup
docker exec -i voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog < backup.sql

Reset Database

WARNING: This deletes all data!

# Complete reset
docker-compose down -v
docker-compose up -d --build

# Wait for MySQL to be healthy
sleep 30

# Run migrations
docker exec voxblog-api sh -c "cd /app/apps/api && pnpm drizzle:migrate"

Verify Database

# Check if containers are running
docker-compose ps

# Check MySQL is healthy
docker-compose ps mysql

# List tables
docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SHOW TABLES;"

# Count posts
docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SELECT COUNT(*) FROM posts;"

# Check migrations
docker exec voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog -e "SELECT * FROM __drizzle_migrations;"

Troubleshooting Checklist

  • MySQL container is running and healthy
  • Environment variables are correct in .env
  • Migrations have been run
  • Tables exist in database
  • API can connect to database (check logs)

Last Updated: 2025-10-26