diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e526e93 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +Dockerfile +.dockerignore +node_modules +npm-debug.log +README.md +.next +.git +.gitignore +*.md +.env +.env.local +.env.development.local +.env.test.local +.env.production.local +.DS_Store +dist diff --git a/.env.example b/.env.example index 6ef22b9..00e4fa4 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ # Meal Planner - Elderly Care Home Meal Ordering System -# SQLite database is stored locally at ./payload.db +# SQLite database is stored locally at ./meal-planner.db # No DATABASE_URL needed for SQLite file-based storage PAYLOAD_SECRET=your-secret-key-change-in-production diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4cb2fff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,59 @@ +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@latest --activate + +# Copy package files +COPY package.json pnpm-lock.yaml ./ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@latest --activate + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Generate Payload types +RUN pnpm generate:types + +# Build the application +RUN pnpm build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +CMD ["node", "server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a183f75 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,73 @@ +version: '3.8' + +services: + postgresql: + image: postgres:16-alpine + container_name: meal-planner-postgres + restart: unless-stopped + environment: + POSTGRES_DB: payload-example-multi-tenant + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - "5433:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - meal-planner-network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + minio: + image: minio/minio:latest + container_name: meal-planner-minio + restart: unless-stopped + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + ports: + - "9100:9000" + - "9101:9001" + volumes: + - minio_data:/data + networks: + - meal-planner-network + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 10s + timeout: 5s + retries: 5 + + app: + build: + context: . + dockerfile: Dockerfile + container_name: meal-planner-app + restart: unless-stopped + environment: + DATABASE_URI: postgres://postgres:postgres@postgresql:5432/payload-example-multi-tenant + PAYLOAD_SECRET: e0d8e16cc9b401535ecf6c6f + PAYLOAD_PUBLIC_SERVER_URL: http://localhost:3100 + SEED_DB: "true" + NODE_ENV: production + ports: + - "3100:3000" + depends_on: + postgresql: + condition: service_healthy + minio: + condition: service_healthy + networks: + - meal-planner-network + +volumes: + postgres_data: + minio_data: + +networks: + meal-planner-network: + driver: bridge