feat: migrate from PostgreSQL to SQLite

- Updated Docker Compose and Dockerfile to remove PostgreSQL dependencies and configure SQLite as the database provider.
- Adjusted environment variables and healthcheck commands to reflect the new database setup.
- Simplified server startup script by removing PostgreSQL wait logic and replacing migration commands with schema push.
- Updated Prisma schema to use SQLite and removed related migration files.
This commit is contained in:
Daniel Luiz Alves
2025-05-30 22:50:40 -03:00
parent 602780e8dd
commit c39d41b76c
8 changed files with 21 additions and 248 deletions

View File

@@ -1,8 +1,7 @@
FROM node:18-alpine AS base FROM node:18-alpine AS base
# Install system dependencies # Install system dependencies (removed netcat-openbsd since we no longer need to wait for PostgreSQL)
RUN apk add --no-cache \ RUN apk add --no-cache \
netcat-openbsd \
gcompat \ gcompat \
supervisor \ supervisor \
curl curl
@@ -77,9 +76,10 @@ RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 palmr RUN adduser --system --uid 1001 palmr
# Create application directories and set permissions # Create application directories and set permissions
# Include storage directories for filesystem mode # Include storage directories for filesystem mode and SQLite database directory
RUN mkdir -p /app/server /app/web /home/palmr/.npm /home/palmr/.cache \ RUN mkdir -p /app/server /app/web /home/palmr/.npm /home/palmr/.cache \
/app/server/uploads /app/server/temp-chunks /app/server/uploads/logo /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo \
/app/server/prisma
RUN chown -R palmr:nodejs /app /home/palmr RUN chown -R palmr:nodejs /app /home/palmr
# === Copy Server Files === # === Copy Server Files ===
@@ -92,7 +92,7 @@ COPY --from=server-builder --chown=palmr:nodejs /app/server/prisma ./prisma
COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./ COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./
# Ensure storage directories have correct permissions # Ensure storage directories have correct permissions
RUN chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks RUN chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma
# === Copy Web Files === # === Copy Web Files ===
WORKDIR /app/web WORKDIR /app/web
@@ -113,7 +113,7 @@ COPY infra/server-start.sh /app/server-start.sh
RUN chmod +x /app/server-start.sh RUN chmod +x /app/server-start.sh
RUN chown palmr:nodejs /app/server-start.sh RUN chown palmr:nodejs /app/server-start.sh
# Copy supervisor configuration # Copy supervisor configuration (simplified without PostgreSQL dependency)
COPY <<EOF /etc/supervisor/conf.d/supervisord.conf COPY <<EOF /etc/supervisor/conf.d/supervisord.conf
[supervisord] [supervisord]
nodaemon=true nodaemon=true
@@ -151,10 +151,11 @@ COPY <<EOF /app/start.sh
echo "Starting Palmr Application..." echo "Starting Palmr Application..."
echo "Storage Mode: \${ENABLE_S3:-false}" echo "Storage Mode: \${ENABLE_S3:-false}"
echo "Database: SQLite"
# Ensure storage directories exist with correct permissions # Ensure storage directories exist with correct permissions
mkdir -p /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo mkdir -p /app/server/uploads /app/server/temp-chunks /app/server/uploads/logo /app/server/prisma
chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks chown -R palmr:nodejs /app/server/uploads /app/server/temp-chunks /app/server/prisma
# Start supervisor # Start supervisor
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
@@ -162,8 +163,8 @@ EOF
RUN chmod +x /app/start.sh RUN chmod +x /app/start.sh
# Create volume mount points for persistent storage (filesystem mode) # Create volume mount points for persistent storage (filesystem mode and SQLite database)
VOLUME ["/app/server/uploads", "/app/server/temp-chunks"] VOLUME ["/app/server/uploads", "/app/server/temp-chunks", "/app/server/prisma"]
# Expose ports # Expose ports
EXPOSE 3333 5487 EXPOSE 3333 5487

View File

@@ -1,4 +1,4 @@
DATABASE_URL="postgresql://palmr:palmr123@localhost:5432/palmr?schema=public" # DATABASE_URL="postgresql://palmr:palmr123@localhost:5432/palmr?schema=public"
FRONTEND_URL="http://localhost:3000" FRONTEND_URL="http://localhost:3000"
MAX_FILESIZE="1073741824" MAX_FILESIZE="1073741824"

View File

@@ -1,178 +0,0 @@
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL,
"firstName" TEXT NOT NULL,
"lastName" TEXT NOT NULL,
"username" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"image" TEXT,
"isAdmin" BOOLEAN NOT NULL DEFAULT false,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "files" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"extension" TEXT NOT NULL,
"size" BIGINT NOT NULL,
"objectName" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "files_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "shares" (
"id" TEXT NOT NULL,
"name" TEXT,
"views" INTEGER NOT NULL DEFAULT 0,
"expiration" TIMESTAMP(3),
"description" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"creatorId" TEXT,
"securityId" TEXT NOT NULL,
CONSTRAINT "shares_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_security" (
"id" TEXT NOT NULL,
"password" TEXT,
"maxViews" INTEGER,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "share_security_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_recipients" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"shareId" TEXT NOT NULL,
CONSTRAINT "share_recipients_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "app_configs" (
"id" TEXT NOT NULL,
"key" TEXT NOT NULL,
"value" TEXT NOT NULL,
"type" TEXT NOT NULL,
"group" TEXT NOT NULL,
"isSystem" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "app_configs_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "login_attempts" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"attempts" INTEGER NOT NULL DEFAULT 1,
"lastAttempt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "login_attempts_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "password_resets" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"token" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"used" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "password_resets_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "share_aliases" (
"id" TEXT NOT NULL,
"alias" TEXT NOT NULL,
"shareId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "share_aliases_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "_ShareFiles" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_ShareFiles_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE UNIQUE INDEX "users_username_key" ON "users"("username");
-- CreateIndex
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
-- CreateIndex
CREATE UNIQUE INDEX "shares_securityId_key" ON "shares"("securityId");
-- CreateIndex
CREATE UNIQUE INDEX "app_configs_key_key" ON "app_configs"("key");
-- CreateIndex
CREATE UNIQUE INDEX "login_attempts_userId_key" ON "login_attempts"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "password_resets_token_key" ON "password_resets"("token");
-- CreateIndex
CREATE UNIQUE INDEX "share_aliases_alias_key" ON "share_aliases"("alias");
-- CreateIndex
CREATE UNIQUE INDEX "share_aliases_shareId_key" ON "share_aliases"("shareId");
-- CreateIndex
CREATE INDEX "_ShareFiles_B_index" ON "_ShareFiles"("B");
-- AddForeignKey
ALTER TABLE "files" ADD CONSTRAINT "files_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "shares" ADD CONSTRAINT "shares_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "shares" ADD CONSTRAINT "shares_securityId_fkey" FOREIGN KEY ("securityId") REFERENCES "share_security"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "share_recipients" ADD CONSTRAINT "share_recipients_shareId_fkey" FOREIGN KEY ("shareId") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "login_attempts" ADD CONSTRAINT "login_attempts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "password_resets" ADD CONSTRAINT "password_resets_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "share_aliases" ADD CONSTRAINT "share_aliases_shareId_fkey" FOREIGN KEY ("shareId") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ShareFiles" ADD CONSTRAINT "_ShareFiles_A_fkey" FOREIGN KEY ("A") REFERENCES "files"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ShareFiles" ADD CONSTRAINT "_ShareFiles_B_fkey" FOREIGN KEY ("B") REFERENCES "shares"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -1,3 +0,0 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

View File

@@ -3,8 +3,8 @@ generator client {
} }
datasource db { datasource db {
provider = "postgresql" provider = "sqlite"
url = env("DATABASE_URL") url = "file:./palmr.db"
} }
model User { model User {

View File

@@ -12,7 +12,6 @@ const envSchema = z.object({
S3_REGION: z.string().optional(), S3_REGION: z.string().optional(),
S3_BUCKET_NAME: z.string().optional(), S3_BUCKET_NAME: z.string().optional(),
S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"), S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"),
DATABASE_URL: z.string().min(1),
MAX_FILESIZE: z.string().min(1), MAX_FILESIZE: z.string().min(1),
}); });

View File

@@ -2,16 +2,12 @@ services:
palmr: palmr:
image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image image: kyantech/palmr:latest # Make sure to use the correct version (latest) of the image
container_name: palmr-application container_name: palmr-application
depends_on:
postgres:
condition: "service_healthy"
environment: environment:
# Storage Configuration # Storage Configuration
- ENABLE_S3=false # Set to 'false' to use local filesystem storage instead of S3/MinIO or true to use S3/MinIO in this case we are using filesystem storage - ENABLE_S3=false # Set to 'false' to use local filesystem storage instead of S3/MinIO or true to use S3/MinIO in this case we are using filesystem storage
- ENCRYPTION_KEY=${ENCRYPTION_KEY:-change-this-key-in-production-min-32-chars} # Required for filesystem encryption (min 32 chars) - ENCRYPTION_KEY=${ENCRYPTION_KEY:-change-this-key-in-production-min-32-chars} # Required for filesystem encryption (min 32 chars)
# Server environment variables # Server environment variables
- DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgresRootPassword}@postgres:${DB_EXTERNAL_PORT:-5432}/${POSTGRES_DB:-palmr_db}?schema=public # Database URL with configurable credentials through env vars
- FRONTEND_URL=http://palmr:${APP_EXTERNAL_PORT:-5487} # Frontend URL - Make sure to use the correct frontend URL, depends on where the frontend is running, its prepared for localhost, but you can change it to your frontend URL if needed - FRONTEND_URL=http://palmr:${APP_EXTERNAL_PORT:-5487} # Frontend URL - Make sure to use the correct frontend URL, depends on where the frontend is running, its prepared for localhost, but you can change it to your frontend URL if needed
- API_BASE_URL=http://palmr:${API_EXTERNAL_PORT:-3333} # Using Docker service name for internal communication - API_BASE_URL=http://palmr:${API_EXTERNAL_PORT:-3333} # Using Docker service name for internal communication
- MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GB. can be changed by admin in the frontend. - MAX_FILESIZE=${MAX_FILESIZE:-1073741824} # Max Filesize for upload - Declared in Bytes. Default is 1GB. can be changed by admin in the frontend.
@@ -21,54 +17,21 @@ services:
volumes: volumes:
- palmr_uploads:/app/server/uploads # Uploads folder for the application - palmr_uploads:/app/server/uploads # Uploads folder for the application
- palmr_temp_chunks:/app/server/temp-chunks # Temp chunks folder for the application - palmr_temp_chunks:/app/server/temp-chunks # Temp chunks folder for the application
networks: - palmr_database:/app/server/prisma # SQLite database folder
- palmr-network # Network for the application to communicate with the database
restart: unless-stopped restart: unless-stopped
healthcheck: healthcheck:
test: [ test: [
"CMD", "CMD",
"sh", "sh",
"-c", "-c",
"wget --no-verbose --tries=1 --spider http://palmr:${API_EXTERNAL_PORT:-3333}/health && wget --no-verbose --tries=1 --spider http://palmr:5487", "wget --no-verbose --tries=1 --spider http://palmr:${API_EXTERNAL_PORT:-3333}/health && wget --no-verbose --tries=1 --spider http://palmr:${APP_EXTERNAL_PORT:-5487}",
] # Healthcheck for the application ] # Healthcheck for the application
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 5 retries: 5
start_period: 120s start_period: 60s # Reduced start period since we don't need to wait for PostgreSQL
postgres:
image: postgres:16-alpine # You can use any postgres version you prefer, but remember that some versions might not be compatible
container_name: palmr-database
environment:
- POSTGRES_USER=${POSTGRES_USER:-postgres} # PostgreSQL username (default: postgres) can be overridden by env var
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgresRootPassword} # PostgreSQL password (default: postgresRootPassword) can be overridden by env var
- POSTGRES_DB=${POSTGRES_DB:-palmr_db} # PostgreSQL database name (default: palmr_db) can be overridden by env var
volumes:
- postgres_data:/var/lib/postgresql/data # PostgreSQL data volume for the application
ports:
- "${DB_EXTERNAL_PORT:-5432}:5432" # PostgreSQL port (default: 5432) can be overridden by env var
networks:
- palmr-network # Network for the application to communicate with the database
restart: unless-stopped
healthcheck:
test: [
"CMD",
"pg_isready",
"-U",
"${POSTGRES_USER:-postgres}",
"-d",
"${POSTGRES_DB:-palmr_db}",
] # Healthcheck for the database
interval: 5s
timeout: 3s
retries: 6
start_period: 30s
volumes: volumes:
postgres_data:
palmr_uploads: palmr_uploads:
palmr_temp_chunks: palmr_temp_chunks:
palmr_database: # Volume for SQLite database persistence
networks:
palmr-network:
driver: bridge

View File

@@ -1,28 +1,19 @@
#!/bin/sh #!/bin/sh
echo "Starting Palmr Server..." echo "Starting Palmr Server with SQLite..."
# Set proper environment # Set proper environment
export HOME=/home/palmr export HOME=/home/palmr
export NPM_CONFIG_CACHE=/home/palmr/.npm export NPM_CONFIG_CACHE=/home/palmr/.npm
export PNPM_HOME=/home/palmr/.pnpm export PNPM_HOME=/home/palmr/.pnpm
# Wait for PostgreSQL - use environment variable or default to postgres
DB_HOST=${DB_HOST:-postgres}
DB_PORT=${DB_PORT:-5432}
echo "Waiting for PostgreSQL at $DB_HOST:$DB_PORT..."
while ! nc -z $DB_HOST $DB_PORT; do
sleep 1
done
echo "PostgreSQL is up!"
cd /app/server cd /app/server
echo "Generating Prisma client..." echo "Generating Prisma client..."
npx prisma generate --schema=./prisma/schema.prisma npx prisma generate --schema=./prisma/schema.prisma
echo "Running migrations..." echo "Pushing database schema..."
npx prisma migrate deploy npx prisma db push --accept-data-loss
echo "Running database seeds..." echo "Running database seeds..."
node prisma/seed.js || echo "Seeds failed or already exist, continuing..." node prisma/seed.js || echo "Seeds failed or already exist, continuing..."