fix: resolve critical production deployment issues
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m21s
Version and Release / version-bump (push) Successful in 33s
Version and Release / trigger-drone (push) Successful in 2s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m21s
Version and Release / version-bump (push) Successful in 33s
Version and Release / trigger-drone (push) Successful in 2s
- Fix database connection error "getaddrinfo ENOTFOUND postgres" - Add wait-for-db.sh script to ensure PostgreSQL is ready before starting - Fix email processor initialization timing issue - Add missing storage path environment variables - Add database dependency to backend service - Enhance health check endpoint with database connectivity check - Update production database defaults to match docker-compose - Install postgresql-client in Docker image for health checks - Document all required environment variables in .env.example Fixes immediate production deployment failures and ensures proper service startup order. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+33
-34
@@ -1,42 +1,41 @@
|
||||
NODE_ENV=development
|
||||
# Backend Environment Variables Example
|
||||
# Copy this file to .env and update with your values
|
||||
|
||||
# Application
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
|
||||
# URLs
|
||||
ADMIN_URL=http://localhost:3000
|
||||
FRONTEND_URL=http://localhost:3001
|
||||
|
||||
# Security
|
||||
JWT_SECRET=dev-secret-key
|
||||
JWT_SECRET=your-very-secure-jwt-secret-at-least-32-characters-long
|
||||
|
||||
# Email Configuration
|
||||
SMTP_HOST=mailhog
|
||||
SMTP_PORT=1025
|
||||
SMTP_SECURE=false
|
||||
SMTP_USER=
|
||||
SMTP_PASS=
|
||||
EMAIL_FROM=noreply@localhost
|
||||
|
||||
# Storage Paths (relative to project root)
|
||||
STORAGE_PATH=./storage
|
||||
EVENTS_PATH=./storage/events
|
||||
ARCHIVE_PATH=./storage/events/archived
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
# URLs
|
||||
ADMIN_URL=https://yourdomain.com
|
||||
FRONTEND_URL=https://yourdomain.com
|
||||
|
||||
# Database Configuration
|
||||
# Development: Use SQLite
|
||||
DATABASE_CLIENT=sqlite3
|
||||
DATABASE_PATH=./data/photo_sharing.db
|
||||
DATABASE_CLIENT=pg
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_USER=picpeak
|
||||
DB_PASSWORD=your-secure-database-password
|
||||
DB_NAME=picpeak
|
||||
|
||||
# Production: Use PostgreSQL
|
||||
# DATABASE_CLIENT=pg
|
||||
# DB_HOST=localhost
|
||||
# DB_PORT=5432
|
||||
# DB_USER=picpeak
|
||||
# DB_PASSWORD=your-secure-password
|
||||
# DB_NAME=picpeak
|
||||
# Email Configuration
|
||||
SMTP_HOST=smtp.example.com
|
||||
SMTP_PORT=587
|
||||
SMTP_SECURE=false
|
||||
SMTP_USER=your-smtp-username
|
||||
SMTP_PASS=your-smtp-password
|
||||
EMAIL_FROM=noreply@yourdomain.com
|
||||
|
||||
# Umami Analytics (optional)
|
||||
UMAMI_URL=
|
||||
UMAMI_WEBSITE_ID=
|
||||
# Storage Paths (Docker)
|
||||
STORAGE_PATH=/app/storage
|
||||
EVENTS_PATH=/app/storage/events
|
||||
ARCHIVE_PATH=/app/storage/events/archived
|
||||
|
||||
# Analytics (Optional)
|
||||
UMAMI_URL=https://analytics.yourdomain.com
|
||||
UMAMI_WEBSITE_ID=your-website-id
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
+6
-3
@@ -16,8 +16,8 @@ FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dumb-init for proper signal handling
|
||||
RUN apk add --no-cache dumb-init
|
||||
# Install dumb-init for proper signal handling and postgresql-client for database checks
|
||||
RUN apk add --no-cache dumb-init postgresql-client
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
||||
@@ -26,6 +26,9 @@ RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
||||
COPY --chown=nodejs:nodejs . .
|
||||
|
||||
# Make wait script executable
|
||||
RUN chmod +x wait-for-db.sh
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p storage/events/active storage/events/archived storage/thumbnails data logs && \
|
||||
chown -R nodejs:nodejs storage data logs
|
||||
@@ -35,4 +38,4 @@ USER nodejs
|
||||
EXPOSE 3000
|
||||
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
CMD ["node", "server.js"]
|
||||
CMD ["./wait-for-db.sh", "node", "server.js"]
|
||||
|
||||
+4
-4
@@ -27,11 +27,11 @@ const config = {
|
||||
production: {
|
||||
client: process.env.DATABASE_CLIENT || 'pg',
|
||||
connection: {
|
||||
host: process.env.DB_HOST || 'postgres',
|
||||
host: process.env.DB_HOST || 'db',
|
||||
port: process.env.DB_PORT || 5432,
|
||||
user: process.env.DB_USER || 'postgres',
|
||||
password: process.env.DB_PASSWORD || 'postgres',
|
||||
database: process.env.DB_NAME || 'photo_sharing'
|
||||
user: process.env.DB_USER || 'picpeak',
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME || 'picpeak'
|
||||
},
|
||||
pool: {
|
||||
min: 2,
|
||||
|
||||
+22
-4
@@ -13,7 +13,7 @@ const path = require('path');
|
||||
const { initializeDatabase } = require('./src/database/db');
|
||||
const { startFileWatcher } = require('./src/services/fileWatcher');
|
||||
const { startExpirationChecker } = require('./src/services/expirationChecker');
|
||||
const { startEmailQueueProcessor } = require('./src/services/emailProcessor');
|
||||
const { initializeTransporter, startEmailQueueProcessor } = require('./src/services/emailProcessor');
|
||||
const { maintenanceMiddleware } = require('./src/middleware/maintenance');
|
||||
const { sessionTimeoutMiddleware } = require('./src/middleware/sessionTimeout');
|
||||
const logger = require('./src/utils/logger');
|
||||
@@ -152,8 +152,25 @@ app.use('/thumbnails', require('./src/middleware/photoAuth'), setCorsHeaders, se
|
||||
app.use('/uploads', setCorsHeaders, secureStatic(path.join(__dirname, 'storage/uploads')));
|
||||
|
||||
// Health check endpoint
|
||||
app.get('/api/health', (req, res) => {
|
||||
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
||||
app.get('/api/health', async (req, res) => {
|
||||
try {
|
||||
// Check database connectivity
|
||||
await db.raw('SELECT 1');
|
||||
|
||||
res.json({
|
||||
status: 'ok',
|
||||
database: 'connected',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Health check failed:', error);
|
||||
res.status(503).json({
|
||||
status: 'error',
|
||||
database: 'disconnected',
|
||||
error: error.message,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Routes
|
||||
@@ -189,7 +206,8 @@ async function startServer() {
|
||||
// Start expiration checker
|
||||
startExpirationChecker();
|
||||
|
||||
// Start email queue processor
|
||||
// Initialize email transporter and start queue processor
|
||||
await initializeTransporter();
|
||||
startEmailQueueProcessor();
|
||||
|
||||
app.listen(PORT, () => {
|
||||
|
||||
@@ -395,12 +395,15 @@ function stopEmailQueueProcessor() {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on module load
|
||||
initializeTransporter().then(() => {
|
||||
startEmailQueueProcessor();
|
||||
});
|
||||
// Initialize on module load - DISABLED for production startup
|
||||
// This will be called from server.js after database is ready
|
||||
// initializeTransporter().then(() => {
|
||||
// startEmailQueueProcessor();
|
||||
// });
|
||||
|
||||
module.exports = {
|
||||
initializeTransporter,
|
||||
startEmailQueueProcessor,
|
||||
sendTemplateEmail,
|
||||
processEmailQueue,
|
||||
queueEmail,
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
# wait-for-db.sh - Wait for PostgreSQL to be ready before starting the application
|
||||
|
||||
set -e
|
||||
|
||||
host="$DB_HOST"
|
||||
port="${DB_PORT:-5432}"
|
||||
user="${DB_USER:-picpeak}"
|
||||
|
||||
echo "Waiting for PostgreSQL at $host:$port..."
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
until PGPASSWORD=$DB_PASSWORD psql -h "$host" -p "$port" -U "$user" -d "${DB_NAME:-picpeak}" -c '\q' 2>/dev/null; do
|
||||
>&2 echo "PostgreSQL is unavailable - sleeping"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
>&2 echo "PostgreSQL is up - executing command"
|
||||
|
||||
# Run migrations
|
||||
echo "Running database migrations..."
|
||||
npm run migrate
|
||||
|
||||
# Execute the main command
|
||||
exec "$@"
|
||||
Reference in New Issue
Block a user