mirror of
https://github.com/kyantech/Palmr.git
synced 2025-11-03 05:23:19 +00:00
feat: add docker-compose files for S3 and local filesystem storage options
Introduce three new docker-compose files: docker-compose-file-system.yaml for local filesystem storage, docker-compose-s3-minio.yaml for MinIO S3-compatible storage, and docker-compose-s3.yaml for direct S3 storage. Each configuration includes environment variables for service setup, health checks, and persistent volume management. This enhances deployment flexibility for the Palmr application.
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
.env
|
||||
.env.*
|
||||
*.log
|
||||
.git
|
||||
.gitignore
|
||||
.next
|
||||
.cache
|
||||
@@ -1,15 +1,16 @@
|
||||
DATABASE_URL="postgresql://palmr:palmr123@localhost:5432/palmr?schema=public"
|
||||
|
||||
FRONTEND_URL="http://localhost:3000"
|
||||
PORT=3333
|
||||
SERVER_IP="localhost"
|
||||
MAX_FILESIZE="1073741824"
|
||||
ENABLE_S3=false
|
||||
ENCRYPTION_KEY=change-this-key-in-production-min-32-chars
|
||||
|
||||
S3_ENDPOINT=localhost
|
||||
S3_PORT=9000
|
||||
S3_USE_SSL=false
|
||||
S3_ACCESS_KEY=minioadmin
|
||||
S3_SECRET_KEY=minioadmin
|
||||
S3_REGION=us-east-1
|
||||
S3_BUCKET_NAME=palmr-files
|
||||
S3_FORCE_PATH_STYLE=true
|
||||
# For use with S3 compatible
|
||||
# S3_ENDPOINT=localhost
|
||||
# S3_PORT=9000
|
||||
# S3_USE_SSL=false
|
||||
# S3_ACCESS_KEY=minioadmin
|
||||
# S3_SECRET_KEY=minioadmin
|
||||
# S3_REGION=us-east-1
|
||||
# S3_BUCKET_NAME=palmr-files
|
||||
# S3_FORCE_PATH_STYLE=true
|
||||
|
||||
1
apps/server/.gitignore
vendored
1
apps/server/.gitignore
vendored
@@ -2,3 +2,4 @@ node_modules
|
||||
.env
|
||||
dist/*
|
||||
uploads/*
|
||||
temp-chunks/*
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app/server
|
||||
|
||||
RUN apk add --no-cache netcat-openbsd
|
||||
RUN npm install -g pnpm
|
||||
|
||||
COPY package*.json ./
|
||||
COPY pnpm-lock.yaml ./
|
||||
COPY prisma ./prisma/
|
||||
COPY scripts ./scripts/
|
||||
|
||||
RUN rm -rf node_modules/.prisma
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
RUN npx prisma generate
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN pnpm build
|
||||
RUN chmod +x ./scripts/start.sh
|
||||
|
||||
EXPOSE 3333
|
||||
|
||||
CMD ["./scripts/start.sh"]
|
||||
22
apps/server/docker-compose-postgres.yaml
Normal file
22
apps/server/docker-compose-postgres.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
postgres:
|
||||
image: bitnami/postgresql:17.2.0
|
||||
container_name: palmr-postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- POSTGRESQL_USERNAME=palmr
|
||||
- POSTGRESQL_PASSWORD=palmr123
|
||||
- POSTGRESQL_DATABASE=palmr
|
||||
volumes:
|
||||
- postgres_data:/bitnami/postgresql
|
||||
restart: "unless-stopped"
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "palmr"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
@@ -1,42 +0,0 @@
|
||||
services:
|
||||
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-03-12T18-04-18Z
|
||||
container_name: minio
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
environment:
|
||||
- MINIO_ROOT_USER=palmr
|
||||
- MINIO_ROOT_PASSWORD=palmr123
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
restart: "unless-stopped"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/ready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
postgres:
|
||||
image: bitnami/postgresql:17.2.0
|
||||
container_name: palmr-postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- POSTGRESQL_USERNAME=palmr
|
||||
- POSTGRESQL_PASSWORD=palmr123
|
||||
- POSTGRESQL_DATABASE=palmr
|
||||
volumes:
|
||||
- postgres_data:/bitnami/postgresql
|
||||
restart: "unless-stopped"
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "palmr"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
@@ -12,9 +12,7 @@ const envSchema = z.object({
|
||||
S3_REGION: z.string().optional(),
|
||||
S3_BUCKET_NAME: z.string().optional(),
|
||||
S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"),
|
||||
PORT: z.string().min(1),
|
||||
DATABASE_URL: z.string().min(1),
|
||||
SERVER_IP: z.string().min(1),
|
||||
MAX_FILESIZE: z.string().min(1),
|
||||
});
|
||||
|
||||
|
||||
@@ -70,15 +70,15 @@ async function startServer() {
|
||||
app.register(healthRoutes);
|
||||
|
||||
await app.listen({
|
||||
port: Number(env.PORT),
|
||||
port: 3333,
|
||||
host: "0.0.0.0",
|
||||
});
|
||||
|
||||
console.log(`🌴 Palmr server running on port ${env.PORT} 🌴`);
|
||||
console.log(`🌴 Palmr server running on port 3333 🌴`);
|
||||
console.log(`📦 Storage mode: ${env.ENABLE_S3 === "true" ? "S3" : "Local Filesystem (Encrypted)"}`);
|
||||
|
||||
console.log("\n📚 API Documentation:");
|
||||
console.log(` - API Reference: http://localhost:${env.PORT}/docs\n`);
|
||||
console.log(` - API Reference: http://localhost:3333/docs\n`);
|
||||
}
|
||||
|
||||
startServer().catch((err) => {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# Use the official Node.js image as the base image
|
||||
|
||||
FROM node:22-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN corepack enable pnpm && pnpm install --frozen-lockfile
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN corepack enable pnpm && pnpm run build
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 5487
|
||||
|
||||
ENV PORT=5487
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
@@ -1,17 +0,0 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "6644:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_TELEMETRY_DISABLED=1
|
||||
- API_BASE_URL=http://host.docker.internal:3333
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
@@ -1,7 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { IconCloudUpload, IconFileText, IconFileTypePdf, IconFileTypography, IconPhoto } from "@tabler/icons-react";
|
||||
import {
|
||||
IconCloudUpload,
|
||||
IconFileText,
|
||||
IconFileTypePdf,
|
||||
IconFileTypography,
|
||||
IconLoader,
|
||||
IconPhoto,
|
||||
} from "@tabler/icons-react";
|
||||
import axios from "axios";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { toast } from "sonner";
|
||||
@@ -181,7 +188,7 @@ export function UploadFileModal({ isOpen, onClose, onSuccess }: UploadFileModalP
|
||||
<div className="space-y-2">
|
||||
<Progress value={uploadProgress} className="w-full" />
|
||||
<p className="text-sm text-gray-500 text-center">
|
||||
{t("uploadFile.uploading")} {uploadProgress}% //!TODO Add translations
|
||||
{t("uploadFile.uploadProgress")}: {uploadProgress}%
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -193,7 +200,11 @@ export function UploadFileModal({ isOpen, onClose, onSuccess }: UploadFileModalP
|
||||
{t("common.cancel")}
|
||||
</Button>
|
||||
<Button variant="default" disabled={!selectedFile || isUploading} onClick={handleUpload}>
|
||||
{isUploading && <IconCloudUpload className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{isUploading ? (
|
||||
<IconLoader className="mr-2 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<IconCloudUpload className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
{t("uploadFile.upload")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
Reference in New Issue
Block a user