Database Migration Guide
Manage database migrations for Imagor Studio deployments.
Migration Behavior
Imagor Studio uses database-type-aware migration handling:
- SQLite: Auto-migration runs during server startup (default)
- PostgreSQL/MySQL: Auto-migration disabled, requires manual migration command
This prevents race conditions in multi-instance production environments.
Migration Tool
Installation
go install github.com/cshum/imagor-studio/server/cmd/imagor-studio-migrate@latest
The Docker image includes both imagor-studio
and imagor-studio-migrate
.
Commands
Run Pending Migrations
imagor-studio-migrate \
--database-url="postgres://user:pass@host:port/db" \
--migrate-command=up
Check Migration Status
imagor-studio-migrate \
--database-url="postgres://user:pass@host:port/db" \
--migrate-command=status
Rollback Last Migration
imagor-studio-migrate \
--database-url="postgres://user:pass@host:port/db" \
--migrate-command=down
Reset All Migrations
This command drops all tables and re-runs migrations. Use only in development!
imagor-studio-migrate \
--database-url="postgres://user:pass@host:port/db" \
--migrate-command=reset
Configuration Methods
The migration tool supports the same configuration system as the main application.
Using Environment Variables
export DATABASE_URL="postgres://user:pass@host:port/db"
export MIGRATE_COMMAND="up"
imagor-studio-migrate
Using .env File
Create a .env
file:
DATABASE_URL=postgres://user:pass@host:port/db
MIGRATE_COMMAND=status
Then run:
imagor-studio-migrate --config .env
Deployment Strategies
Single Instance (SQLite)
Auto-migration runs automatically:
imagor-studio
No manual migration needed!
Multi-Instance (PostgreSQL/MySQL)
Run migrations before starting application instances:
# 1. Run migrations
imagor-studio-migrate \
--database-url="$DATABASE_URL" \
--migrate-command=up
# 2. Start application
imagor-studio --database-url="$DATABASE_URL"
Docker Deployment
Docker Command
# Run migrations
docker run --rm \
-e DATABASE_URL="postgres://user:pass@host:port/db" \
shumc/imagor-studio \
imagor-studio-migrate --migrate-command=up
# Start application
docker run -p 8000:8000 \
-e DATABASE_URL="postgres://user:pass@host:port/db" \
shumc/imagor-studio
Docker Compose
version: "3.8"
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: imagor_studio
POSTGRES_USER: imagor
POSTGRES_PASSWORD: secure_password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U imagor -d imagor_studio"]
interval: 5s
timeout: 5s
retries: 5
migrate:
image: shumc/imagor-studio:latest
command: ["imagor-studio-migrate", "--migrate-command=up"]
environment:
- DATABASE_URL=postgres://imagor:secure_password@postgres:5432/imagor_studio
depends_on:
postgres:
condition: service_healthy
imagor-studio:
image: shumc/imagor-studio:latest
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgres://imagor:secure_password@postgres:5432/imagor_studio
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
volumes:
postgres_data:
Kubernetes Deployment
Migration Job
apiVersion: batch/v1
kind: Job
metadata:
name: imagor-studio-migrate
spec:
template:
spec:
containers:
- name: migrate
image: shumc/imagor-studio:latest
command: ["imagor-studio-migrate", "--migrate-command=up"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secret
key: url
restartPolicy: OnFailure
Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: imagor-studio
spec:
replicas: 3
selector:
matchLabels:
app: imagor-studio
template:
metadata:
labels:
app: imagor-studio
spec:
containers:
- name: app
image: shumc/imagor-studio:latest
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secret
key: url
ports:
- containerPort: 8000
Deploy in order:
# 1. Run migration job
kubectl apply -f migration-job.yaml
kubectl wait --for=condition=complete job/imagor-studio-migrate
# 2. Deploy application
kubectl apply -f deployment.yaml
Migration Files
Migrations are embedded in the application binary. Current migrations:
- 20250504_create_metadata_table.go - Initial metadata table
- 20250816_create_users_table.go - User authentication
- 20250831_add_is_encrypted_to_registry.go - Encryption support
- 20250923_add_video_extensions.go - Video file support
Troubleshooting
Migration Fails
Check migration status:
imagor-studio-migrate \
--database-url="$DATABASE_URL" \
--migrate-command=status
Locked Migrations
If migrations are locked (rare), manually unlock:
-- PostgreSQL
DELETE FROM schema_migrations WHERE dirty = true;
-- MySQL
DELETE FROM schema_migrations WHERE dirty = 1;
Version Conflicts
Ensure all instances run the same version:
docker pull shumc/imagor-studio:latest
Database Connection Issues
Verify database connectivity:
# PostgreSQL
psql "$DATABASE_URL"
# MySQL
mysql -h host -u user -p database
Best Practices
- Always backup before running migrations
- Test migrations in staging environment first
- Run migrations before deploying new versions
- Monitor migration logs for errors
- Use version tags for production deployments
Next Steps
- Database Configuration - Configure your database
- Docker Deployment - Deploy with Docker
- Kubernetes Deployment - Deploy on Kubernetes