mirror of
https://github.com/LogicLabs-OU/OpenArchiver.git
synced 2026-04-06 00:31:57 +02:00
Docker deployment
This commit is contained in:
46
.dockerignore
Normal file
46
.dockerignore
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Node
|
||||||
|
node_modules
|
||||||
|
.pnpm-store
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!/.env.example
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDEs
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
docker-compose.yml
|
||||||
|
.dockerignore
|
||||||
|
Dockerfile
|
||||||
|
|
||||||
|
# Local data
|
||||||
|
meili_data
|
||||||
@@ -3,6 +3,7 @@ NODE_ENV=development
|
|||||||
PORT_BACKEND=4000
|
PORT_BACKEND=4000
|
||||||
PORT_FRONTEND=3000
|
PORT_FRONTEND=3000
|
||||||
|
|
||||||
|
|
||||||
# PostgreSQL
|
# PostgreSQL
|
||||||
DATABASE_URL="postgresql://admin:password@postgres:5432/open_archive?schema=public"
|
DATABASE_URL="postgresql://admin:password@postgres:5432/open_archive?schema=public"
|
||||||
|
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
frontend:
|
|
||||||
build:
|
|
||||||
context: ./packages/frontend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- '3000:3000'
|
|
||||||
depends_on:
|
|
||||||
- backend-api
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
backend-api:
|
|
||||||
build:
|
|
||||||
context: ./packages/backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- '4000:4000'
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
ingestion-worker:
|
|
||||||
build:
|
|
||||||
context: ./packages/backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
command: 'pnpm ts-node-dev --respawn --transpile-only src/workers/ingestion.worker.ts'
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
indexing-worker:
|
|
||||||
build:
|
|
||||||
context: ./packages/backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
command: 'pnpm ts-node-dev --respawn --transpile-only src/workers/indexing.worker.ts'
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
sync-scheduler:
|
|
||||||
build:
|
|
||||||
context: ./packages/backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
command: 'pnpm ts-node-dev --respawn --transpile-only src/jobs/schedulers/sync-scheduler.ts'
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:15
|
|
||||||
ports:
|
|
||||||
- '5432:5432'
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7
|
|
||||||
ports:
|
|
||||||
- '6379:6379'
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
|
|
||||||
meilisearch:
|
|
||||||
image: getmeili/meilisearch:v1.3
|
|
||||||
ports:
|
|
||||||
- '7700:7700'
|
|
||||||
volumes:
|
|
||||||
- meili_data:/meili_data
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
redis_data:
|
|
||||||
meili_data:
|
|
||||||
|
|||||||
53
docker/Dockerfile
Normal file
53
docker/Dockerfile
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Dockerfile for Open Archiver
|
||||||
|
|
||||||
|
# 1. Build Stage: Install all dependencies and build the project
|
||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Copy manifests and lockfile
|
||||||
|
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||||
|
COPY packages/backend/package.json ./packages/backend/
|
||||||
|
COPY packages/frontend/package.json ./packages/frontend/
|
||||||
|
COPY packages/types/package.json ./packages/types/
|
||||||
|
|
||||||
|
# Install all dependencies
|
||||||
|
RUN pnpm install --frozen-lockfile --prod=false
|
||||||
|
|
||||||
|
# Copy the rest of the source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build all packages
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
# 2. Production Stage: Install only production dependencies and copy built artifacts
|
||||||
|
FROM node:22-alpine AS production
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Copy manifests and lockfile
|
||||||
|
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||||
|
COPY packages/backend/package.json ./packages/backend/
|
||||||
|
COPY packages/frontend/package.json ./packages/frontend/
|
||||||
|
COPY packages/types/package.json ./packages/types/
|
||||||
|
|
||||||
|
# Install only production dependencies
|
||||||
|
RUN pnpm install --frozen-lockfile --prod
|
||||||
|
|
||||||
|
# Copy built application from build stage
|
||||||
|
COPY --from=build /app/packages/backend/dist ./packages/backend/dist
|
||||||
|
COPY --from=build /app/packages/frontend/build ./packages/frontend/build
|
||||||
|
COPY --from=build /app/packages/types/dist ./packages/types/dist
|
||||||
|
COPY --from=build /app/packages/backend/drizzle.config.ts ./packages/backend/drizzle.config.ts
|
||||||
|
COPY --from=build /app/packages/backend/src/database/migrations ./packages/backend/src/database/migrations
|
||||||
|
|
||||||
|
# Expose the port the app runs on
|
||||||
|
EXPOSE 4000
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["pnpm", "docker-start"]
|
||||||
14
package.json
14
package.json
@@ -4,11 +4,19 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "dotenv -- pnpm --filter \"./packages/*\" --parallel dev",
|
"dev": "dotenv -- pnpm --filter \"./packages/*\" --parallel dev",
|
||||||
"build": "pnpm --filter \"./packages/*\" --parallel build",
|
"build": "pnpm --filter \"./packages/*\" --parallel build",
|
||||||
"start:workers": "dotenv -- concurrently \"pnpm --filter @open-archiver/backend start:ingestion-worker\" \"pnpm --filter @open-archiver/backend start:indexing-worker\" \"pnpm --filter @open-archiver/backend start:sync-scheduler\""
|
"start": "dotenv -- pnpm --filter \"./packages/*\" --parallel start",
|
||||||
|
"start:workers": "dotenv -- concurrently \"pnpm --filter @open-archiver/backend start:ingestion-worker\" \"pnpm --filter @open-archiver/backend start:indexing-worker\" \"pnpm --filter @open-archiver/backend start:sync-scheduler\"",
|
||||||
|
"start:workers:dev": "dotenv -- concurrently \"pnpm --filter @open-archiver/backend start:ingestion-worker:dev\" \"pnpm --filter @open-archiver/backend start:indexing-worker:dev\" \"pnpm --filter @open-archiver/backend start:sync-scheduler:dev\"",
|
||||||
|
"db:generate": "dotenv -- pnpm --filter @open-archiver/backend db:generate",
|
||||||
|
"db:migrate": "dotenv -- pnpm --filter @open-archiver/backend db:migrate",
|
||||||
|
"db:migrate:dev": "dotenv -- pnpm --filter @open-archiver/backend db:migrate:dev",
|
||||||
|
"docker-start": "pnpm db:migrate && concurrently \"pnpm start:workers\" \"pnpm start\""
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"concurrently": "^9.2.0",
|
||||||
|
"dotenv-cli": "8.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^9.2.0",
|
|
||||||
"dotenv-cli": "8.0.0",
|
|
||||||
"typescript": "5.8.3"
|
"typescript": "5.8.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.13.1",
|
"packageManager": "pnpm@10.13.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineConfig } from 'drizzle-kit';
|
import { defineConfig } from 'drizzle-kit';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
|
|
||||||
config({ path: '../../.env' });
|
config();
|
||||||
|
|
||||||
if (!process.env.DATABASE_URL) {
|
if (!process.env.DATABASE_URL) {
|
||||||
throw new Error('DATABASE_URL is not set in the .env file');
|
throw new Error('DATABASE_URL is not set in the .env file');
|
||||||
|
|||||||
@@ -6,16 +6,20 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "ts-node-dev --respawn --transpile-only src/index.ts ",
|
"dev": "ts-node-dev --respawn --transpile-only src/index.ts ",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"prestart": "npm run build",
|
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"start:ingestion-worker": "ts-node-dev --respawn --transpile-only src/workers/ingestion.worker.ts",
|
"start:ingestion-worker": "node dist/workers/ingestion.worker.js",
|
||||||
"start:indexing-worker": "ts-node-dev --respawn --transpile-only src/workers/indexing.worker.ts",
|
"start:indexing-worker": "node dist/workers/indexing.worker.js",
|
||||||
"start:sync-scheduler": "ts-node-dev --respawn --transpile-only src/jobs/schedulers/sync-scheduler.ts",
|
"start:sync-scheduler": "node dist/jobs/schedulers/sync-scheduler.js",
|
||||||
|
"start:ingestion-worker:dev": "ts-node-dev --respawn --transpile-only src/workers/ingestion.worker.ts",
|
||||||
|
"start:indexing-worker:dev": "ts-node-dev --respawn --transpile-only src/workers/indexing.worker.ts",
|
||||||
|
"start:sync-scheduler:dev": "ts-node-dev --respawn --transpile-only src/jobs/schedulers/sync-scheduler.ts",
|
||||||
"db:generate": "drizzle-kit generate --config=drizzle.config.ts",
|
"db:generate": "drizzle-kit generate --config=drizzle.config.ts",
|
||||||
"db:push": "drizzle-kit push --config=drizzle.config.ts",
|
"db:push": "drizzle-kit push --config=drizzle.config.ts",
|
||||||
"db:migrate": "ts-node-dev src/database/migrate.ts"
|
"db:migrate": "node dist/database/migrate.js",
|
||||||
|
"db:migrate:dev": "ts-node-dev src/database/migrate.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"drizzle-kit": "^0.31.4",
|
||||||
"@aws-sdk/client-s3": "^3.844.0",
|
"@aws-sdk/client-s3": "^3.844.0",
|
||||||
"@aws-sdk/lib-storage": "^3.844.0",
|
"@aws-sdk/lib-storage": "^3.844.0",
|
||||||
"@azure/msal-node": "^3.6.3",
|
"@azure/msal-node": "^3.6.3",
|
||||||
@@ -55,7 +59,6 @@
|
|||||||
"@types/microsoft-graph": "^2.40.1",
|
"@types/microsoft-graph": "^2.40.1",
|
||||||
"@types/node": "^24.0.12",
|
"@types/node": "^24.0.12",
|
||||||
"bull-board": "^2.1.3",
|
"bull-board": "^2.1.3",
|
||||||
"drizzle-kit": "^0.31.4",
|
|
||||||
"ts-node-dev": "^2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { drizzle } from 'drizzle-orm/postgres-js';
|
|||||||
import postgres from 'postgres';
|
import postgres from 'postgres';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
|
|
||||||
config({ path: '../../.env' });
|
config();
|
||||||
|
|
||||||
const runMigrate = async () => {
|
const runMigrate = async () => {
|
||||||
if (!process.env.DATABASE_URL) {
|
if (!process.env.DATABASE_URL) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
"start": "node build/index.js",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"prepare": "svelte-kit sync || echo ''",
|
"prepare": "svelte-kit sync || echo ''",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
@@ -19,18 +20,21 @@
|
|||||||
"jose": "^6.0.1",
|
"jose": "^6.0.1",
|
||||||
"lucide-svelte": "^0.525.0",
|
"lucide-svelte": "^0.525.0",
|
||||||
"postal-mime": "^2.4.4",
|
"postal-mime": "^2.4.4",
|
||||||
"svelte-persisted-store": "^0.12.0"
|
"svelte-persisted-store": "^0.12.0",
|
||||||
|
"@sveltejs/kit": "^2.16.0",
|
||||||
|
"bits-ui": "^2.8.10",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"tailwind-variants": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@internationalized/date": "^3.8.2",
|
"@internationalized/date": "^3.8.2",
|
||||||
"@lucide/svelte": "^0.515.0",
|
"@lucide/svelte": "^0.515.0",
|
||||||
"@sveltejs/adapter-auto": "^6.0.0",
|
"@sveltejs/adapter-auto": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/adapter-node": "^5.2.13",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"@types/d3-shape": "^3.1.7",
|
"@types/d3-shape": "^3.1.7",
|
||||||
"bits-ui": "^2.8.10",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"dotenv": "^17.2.0",
|
"dotenv": "^17.2.0",
|
||||||
"layerchart": "2.0.0-next.27",
|
"layerchart": "2.0.0-next.27",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
@@ -38,8 +42,6 @@
|
|||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwind-merge": "^3.3.1",
|
|
||||||
"tailwind-variants": "^1.0.0",
|
|
||||||
"tailwindcss": "^4.0.0",
|
"tailwindcss": "^4.0.0",
|
||||||
"tw-animate-css": "^1.3.5",
|
"tw-animate-css": "^1.3.5",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { authStore } from '$lib/stores/auth.store';
|
import { authStore } from '$lib/stores/auth.store';
|
||||||
import type { User } from '@open-archiver/types';
|
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
const BASE_URL = '/api/v1'; // Using a relative URL for proxying
|
const BASE_URL = '/api/v1'; // Using a relative URL for proxying
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { RequestEvent } from '@sveltejs/kit';
|
|||||||
|
|
||||||
const BASE_URL = '/api/v1'; // Using a relative URL for proxying
|
const BASE_URL = '/api/v1'; // Using a relative URL for proxying
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom fetch wrapper for the server-side to automatically handle authentication headers.
|
* A custom fetch wrapper for the server-side to automatically handle authentication headers.
|
||||||
* @param url The URL to fetch, relative to the API base.
|
* @param url The URL to fetch, relative to the API base.
|
||||||
|
|||||||
30
packages/frontend/src/routes/api/[...slug]/+server.ts
Normal file
30
packages/frontend/src/routes/api/[...slug]/+server.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { env } from '$env/dynamic/private';
|
||||||
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
const BACKEND_URL = `http://localhost:${env.PORT_BACKEND || 4000}`;
|
||||||
|
|
||||||
|
const handleRequest: RequestHandler = async ({ request, params }) => {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const slug = params.slug || '';
|
||||||
|
const targetUrl = `${BACKEND_URL}/${slug}${url.search}`;
|
||||||
|
|
||||||
|
// Create a new request with the same method, headers, and body
|
||||||
|
const proxyRequest = new Request(targetUrl, {
|
||||||
|
method: request.method,
|
||||||
|
headers: request.headers,
|
||||||
|
body: request.body,
|
||||||
|
duplex: 'half' // Required for streaming request bodies
|
||||||
|
} as RequestInit);
|
||||||
|
|
||||||
|
// Forward the request to the backend
|
||||||
|
const response = await fetch(proxyRequest);
|
||||||
|
|
||||||
|
// Return the response from the backend
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GET = handleRequest;
|
||||||
|
export const POST = handleRequest;
|
||||||
|
export const PUT = handleRequest;
|
||||||
|
export const PATCH = handleRequest;
|
||||||
|
export const DELETE = handleRequest;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import adapter from '@sveltejs/adapter-auto';
|
import adapter from '@sveltejs/adapter-node';
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
|||||||
Reference in New Issue
Block a user