Fix: Strapi Database Auto-Creation¶
Problem¶
Strapi CMS fails to start with error:
This occurs when the PostgreSQL database for Strapi hasn't been created yet.
Root Cause¶
The init-multiple-databases.sh script only runs when PostgreSQL is first initialized (when the data volume is empty). If:
- PostgreSQL was already initialized
- The database was deleted
- The POSTGRES_MULTIPLE_DATABASES environment variable wasn't set during initialization
Then the strapi_qual database won't exist, causing Strapi to fail on startup.
Solution¶
Added auto-creation logic to Strapi's bootstrap function, similar to what was implemented for notification-service and user-management. The database is now automatically created if it doesn't exist when Strapi starts.
Implementation¶
Modified File¶
services/strapi-cms/src/index.ts
Changes¶
- Added
ensureDatabase()function: - Parses
DATABASE_URLto extract database name - Attempts to connect to the database
- If database doesn't exist (error code
3D000), creates it -
Connects to default
postgresdatabase to create the target database -
Updated
bootstrap()function: - Calls
ensureDatabase()before Strapi connects to the database - Only runs if
DATABASE_CLIENTispostgresorDATABASE_URLis set - Handles errors gracefully (doesn't prevent Strapi from starting)
Code Example¶
async function ensureDatabase() {
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
console.warn('DATABASE_URL not set. Skipping database auto-creation.');
return;
}
// Parse database URL to extract database name
const url = new URL(databaseUrl);
const databaseName = url.pathname.slice(1);
// Try to connect to the database
try {
const testPool = new Pool({
connectionString: databaseUrl,
ssl: false as any,
});
const testClient = await testPool.connect();
testClient.release();
await testPool.end();
console.log(`Database '${databaseName}' exists and is accessible.`);
} catch (error: any) {
// If database doesn't exist, create it
if (error.code === '3D000' || error.message?.includes('does not exist')) {
console.log(`Database '${databaseName}' does not exist. Attempting to create it...`);
// Connect to default 'postgres' database to create the target database
const adminUrl = new URL(databaseUrl);
adminUrl.pathname = '/postgres';
const adminPool = new Pool({
connectionString: adminUrl.toString(),
ssl: false as any,
});
const client = await adminPool.connect();
try {
// Check if database already exists
const checkResult = await client.query(
'SELECT 1 FROM pg_database WHERE datname = $1',
[databaseName]
);
if (checkResult.rows.length === 0) {
// Escape database name to prevent SQL injection
const escapedDbName = `"${databaseName.replace(/"/g, '""')}"`;
await client.query(`CREATE DATABASE ${escapedDbName}`);
console.log(`✅ Database '${databaseName}' created successfully`);
} else {
console.log(`Database '${databaseName}' already exists`);
}
} catch (createError: any) {
console.error(`Failed to create database '${databaseName}':`, createError.message);
throw createError;
} finally {
client.release();
await adminPool.end();
}
} else {
console.error('Failed to connect to database:', error.message);
throw error;
}
}
}
Verification¶
After deploying the fix, Strapi should:
- On first startup:
- Detect that
strapi_qualdoesn't exist - Create the database automatically
- Log:
✅ Database 'strapi_qual' created successfully -
Continue with normal startup
-
On subsequent startups:
- Detect that database exists
- Log:
Database 'strapi_qual' exists and is accessible. - Continue with normal startup
Manual Database Creation (Alternative)¶
If you need to create the database manually:
# Connect to PostgreSQL container
docker exec -it po-postgres psql -U postgres
# Create database
CREATE DATABASE strapi_qual;
# Grant permissions (if needed)
GRANT ALL PRIVILEGES ON DATABASE strapi_qual TO postgres;
# Exit
\q
Related Services¶
This same auto-creation pattern is used in:
- notification-service (services/notification-service/src/common/database/database.service.ts)
- user-management (services/user-management/src/db.ts)
Dependencies¶
pgpackage (already inpackage.json)- PostgreSQL connection credentials from
DATABASE_URLenvironment variable
Notes¶
- The auto-creation only works if the PostgreSQL user has
CREATEDBprivilege (whichpostgresuser has by default) - Database name is extracted from
DATABASE_URLenvironment variable - The function gracefully handles errors and doesn't prevent Strapi from starting if database creation fails