All checks were successful
Deploy to Production / deploy (push) Successful in 1m45s
- 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
209 lines
4.7 KiB
Markdown
209 lines
4.7 KiB
Markdown
# Database Setup & Troubleshooting
|
|
|
|
## Initial Setup
|
|
|
|
**✅ Migrations now run automatically!** When you start the API, it will automatically run any pending database migrations.
|
|
|
|
### Quick Setup
|
|
|
|
```bash
|
|
# 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:
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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`:
|
|
|
|
```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:
|
|
```bash
|
|
docker-compose down -v
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
## Backup & Restore
|
|
|
|
### Backup
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Restore from backup
|
|
docker exec -i voxblog-mysql mysql -u voxblog -pvoxblogAppPass123! voxblog < backup.sql
|
|
```
|
|
|
|
## Reset Database
|
|
|
|
**WARNING: This deletes all data!**
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|