From d40ef516955a65a802c42e2faa68be273715ae93 Mon Sep 17 00:00:00 2001 From: Daniel Luiz Alves Date: Tue, 27 May 2025 00:50:46 -0300 Subject: [PATCH] chore: add Dockerfile, docker-compose, and .dockerignore for multi-service setup Introduce a Dockerfile for building the Palmr application with multi-stage builds for both server and web components. Update docker-compose.yaml to consolidate services under a single 'palmr' service, ensuring proper health checks and environment variable configurations. Add a .dockerignore file to optimize Docker builds by excluding unnecessary files. Include a Makefile for simplified build and deployment commands. --- .dockerignore | 70 ++++++++ Dockerfile | 160 ++++++++++++++++++ Makefile | 47 +++++ .../content/docs/2.0.0-beta/installation.mdx | 51 +++--- apps/docs/content/docs/2.0.0-beta/meta.json | 2 +- apps/docs/src/app/(home)/page.tsx | 7 +- apps/docs/src/app/api/search/route.ts | 10 +- apps/docs/src/app/layout.tsx | 5 +- apps/server/package.json | 5 +- apps/server/prisma/{seed.ts => seed.js} | 49 +++--- apps/server/scripts/check-db.mjs | 17 -- apps/server/scripts/start.sh | 27 --- docker-compose.yaml | 38 ++--- infra/SCRIPTS.md | 33 ++++ infra/build-docker.sh | 43 +++++ infra/server-start.sh | 29 ++++ 16 files changed, 466 insertions(+), 127 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 Makefile rename apps/server/prisma/{seed.ts => seed.js} (68%) delete mode 100644 apps/server/scripts/check-db.mjs delete mode 100644 apps/server/scripts/start.sh create mode 100644 infra/SCRIPTS.md create mode 100755 infra/build-docker.sh create mode 100644 infra/server-start.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..27de3da --- /dev/null +++ b/.dockerignore @@ -0,0 +1,70 @@ +# Git +.git +.gitignore + +# Documentation +README.md +CONTRIBUTING.md +*.md + +# Node modules +node_modules +*/node_modules +**/node_modules + +# Build outputs +.next +dist +build + +# Development files +.env* +.vscode +.idea + +# Logs +*.log +logs + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Dependency directories +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# Docker files +Dockerfile* +docker-compose* + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b8963c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,160 @@ +FROM node:18-alpine AS base + +# Install system dependencies +RUN apk add --no-cache \ + netcat-openbsd \ + gcompat \ + supervisor \ + curl + +# Enable pnpm +RUN corepack enable pnpm + +# Set working directory +WORKDIR /app + +# === SERVER BUILD STAGE === +FROM base AS server-deps +WORKDIR /app/server + +# Copy server package files +COPY apps/server/package*.json ./ +COPY apps/server/pnpm-lock.yaml ./ + +# Install server dependencies +RUN pnpm install --frozen-lockfile + +FROM base AS server-builder +WORKDIR /app/server + +# Copy server dependencies +COPY --from=server-deps /app/server/node_modules ./node_modules + +# Copy server source code +COPY apps/server/ ./ + +# Generate Prisma client +RUN npx prisma generate + +# Build server +RUN pnpm build + +# === WEB BUILD STAGE === +FROM base AS web-deps +WORKDIR /app/web + +# Copy web package files +COPY apps/web/package.json apps/web/pnpm-lock.yaml ./ + +# Install web dependencies +RUN pnpm install --frozen-lockfile + +FROM base AS web-builder +WORKDIR /app/web + +# Copy web dependencies +COPY --from=web-deps /app/web/node_modules ./node_modules + +# Copy web source code +COPY apps/web/ ./ + +# Set environment variables for build +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Build web application +RUN pnpm run build + +# === PRODUCTION STAGE === +FROM base AS runner + +# Set production environment +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +# Create application user +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 palmr + +# Create application directories and set permissions +RUN mkdir -p /app/server /app/web /home/palmr/.npm /home/palmr/.cache +RUN chown -R palmr:nodejs /app /home/palmr + +# === Copy Server Files === +WORKDIR /app/server + +# Copy server production files +COPY --from=server-builder --chown=palmr:nodejs /app/server/dist ./dist +COPY --from=server-builder --chown=palmr:nodejs /app/server/node_modules ./node_modules +COPY --from=server-builder --chown=palmr:nodejs /app/server/prisma ./prisma +COPY --from=server-builder --chown=palmr:nodejs /app/server/package.json ./ + +# === Copy Web Files === +WORKDIR /app/web + +# Copy web production files +COPY --from=web-builder --chown=palmr:nodejs /app/web/public ./public +COPY --from=web-builder --chown=palmr:nodejs /app/web/.next/standalone ./ +COPY --from=web-builder --chown=palmr:nodejs /app/web/.next/static ./.next/static + +# === Setup Supervisor === +WORKDIR /app + +# Create supervisor configuration +RUN mkdir -p /etc/supervisor/conf.d /var/log/supervisor + +# Copy server start script +COPY infra/server-start.sh /app/server-start.sh +RUN chmod +x /app/server-start.sh +RUN chown palmr:nodejs /app/server-start.sh + +# Copy supervisor configuration +COPY <โ€ข Depends on services: postgres and minio
โ€ข Has healthcheck to ensure availability | -| palmr-app (Frontend) | [kyantech/palmr-app:latest](https://hub.docker.com/repository/docker/kyantech/palmr-app/tags/latest/sha256-33f568673ae8cc8529532146b6afc1acafa203387ced6c7bb3451a7ab4198a2f) | **5487** | โ€ข Web application interface
โ€ข Depends on palmr-api service
โ€ข Configured for production environment | +| palmr | [kyantech/palmr:latest](https://hub.docker.com/repository/docker/kyantech/palmr/general) | **3333** (API)
**5487** (Web) | โ€ข Combined backend API and frontend service
โ€ข Depends on services: postgres and minio
โ€ข Has healthcheck to ensure availability | | minio (Storage) | [minio/minio:RELEASE.2025-03-12T18-04-18Z](https://hub.docker.com/layers/minio/minio/RELEASE.2025-03-12T18-04-18Z/images/sha256-85f3e4cd1ca92a2711553ab79f222bcd8b75aa2c77a1a0b0ccf80d38e8ab2fe5) | **6421**(API)
**6422**(Console) | โ€ข File storage service
โ€ข Persistent volume for data | | minio-init (Config) | [minio/mc:RELEASE.2025-03-12T17-29-24Z](https://hub.docker.com/layers/minio/mc/RELEASE.2025-03-12T17-29-24Z/images/sha256-68d8c80f43908b02daa285e55547131870a1d36b3ffe272c26d7d8f4d52d1e5c) | N/A | โ€ข Initially configures the "files" bucket
โ€ข Runs only once during initialization | | postgres (Database) | [bitnami/postgresql:17.2.0](https://hub.docker.com/layers/bitnami/postgresql/17.2.0/images/sha256-29c614afad4f514b12b5c0f4d006f38c98fa4b18c3582732ff93b3fe9a79d875) | **5432** | โ€ข PostgreSQL database
โ€ข Persistent volume for data | @@ -197,13 +184,17 @@ The table below shows all environment variables that can be set In a localhost environment, there's no mystery. If you don't want to change any service exposure ports, you can simply run: +```bash +docker compose pull && docker compose up -d +``` + This will execute all necessary services and give you access to the following URLs (if you haven't changed any ports): - **Frontend:** [http://localhost:5487](http://localhost:5487) - **Backend:** [http://localhost:3333](http://localhost:3333/) - **MinIO API:** [http://localhost:6421](http://localhost:6421) - **MinIO Console:** [http://localhost:6422](http://localhost:6422) -- **Postgres Database:** [http://localhost:5423](http://localhost:5423/) (Connection only) +- **Postgres Database:** [http://localhost:5432](http://localhost:5432/) (Connection only) > *If you have changed any port, simply access the URL with the port you configured.* > @@ -247,7 +238,7 @@ If you haven't changed the execution ports, you'll have access on your server at - **Backend:** `[server_ip]:3333` - **MinIO API:** `[server_ip]:6421` - **MinIO Console:** `[server_ip]:6422` -- **Postgres Database:** `[server_ip]:5423` (Connection only) +- **Postgres Database:** `[server_ip]:5432` (Connection only) > *If you've changed any port, simply access the URL with the port you configured.* > diff --git a/apps/docs/content/docs/2.0.0-beta/meta.json b/apps/docs/content/docs/2.0.0-beta/meta.json index 45dad19..29b1f2d 100644 --- a/apps/docs/content/docs/2.0.0-beta/meta.json +++ b/apps/docs/content/docs/2.0.0-beta/meta.json @@ -25,4 +25,4 @@ "gh-sponsor", "..." ] -} +} \ No newline at end of file diff --git a/apps/docs/src/app/(home)/page.tsx b/apps/docs/src/app/(home)/page.tsx index edce249..1ddc06e 100644 --- a/apps/docs/src/app/(home)/page.tsx +++ b/apps/docs/src/app/(home)/page.tsx @@ -83,7 +83,12 @@ export default function HomePage() { function Hero() { return (
-

๐ŸŒด Palmr. v2.0.0-beta

+

+ ๐ŸŒด Palmr.{" "} + + v2.0.0-beta + +

Modern & efficient file sharing

diff --git a/apps/docs/src/app/api/search/route.ts b/apps/docs/src/app/api/search/route.ts index f43b462..20e01b5 100644 --- a/apps/docs/src/app/api/search/route.ts +++ b/apps/docs/src/app/api/search/route.ts @@ -1,6 +1,6 @@ -import { source } from '@/lib/source'; -import { createFromSource } from 'fumadocs-core/search/server'; - +import { source } from "@/lib/source"; +import { createFromSource } from "fumadocs-core/search/server"; + export const { GET } = createFromSource(source, (page) => { return { title: page.data.title, @@ -8,6 +8,8 @@ export const { GET } = createFromSource(source, (page) => { url: page.url, id: page.url, structuredData: page.data.structuredData, - tag: page.url.startsWith('/docs/2.0.0-beta') ? 'v2.0.0-beta' : 'v1.1.7-beta' + tag: page.url.startsWith("/docs/2.0.0-beta") + ? "v2.0.0-beta" + : "v1.1.7-beta", }; }); diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index 0087922..831b608 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -11,14 +11,15 @@ const inter = Inter({ export const metadata = { title: "๐ŸŒด Palmr. | Official Website", - description: "Palmr. is a fast, simple and powerful document sharing platform.", + description: + "Palmr. is a fast, simple and powerful document sharing platform.", }; export default function Layout({ children }: { children: ReactNode }) { return ( -