Compare commits
8 Commits
feat/reduc
...
feat/smtp-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09a190d6fb | ||
|
|
5586c26c12 | ||
|
|
2d7097eb83 | ||
|
|
2aa898da00 | ||
|
|
a01a826bac | ||
|
|
a29ea76024 | ||
|
|
e1c6bfd6cd | ||
|
|
c272c38f6b |
@@ -1,84 +0,0 @@
|
|||||||
ARG NODE_VERSION=20
|
|
||||||
ARG APP_DIRNAME=web
|
|
||||||
ARG PROJECT=@kan/web
|
|
||||||
|
|
||||||
# 1. Alpine image
|
|
||||||
FROM node:${NODE_VERSION}-alpine AS alpine
|
|
||||||
RUN apk update
|
|
||||||
RUN apk add --no-cache libc6-compat python3 make g++
|
|
||||||
|
|
||||||
# Setup pnpm and turbo on the alpine base
|
|
||||||
FROM alpine AS base
|
|
||||||
RUN corepack enable
|
|
||||||
# Replace <your-major-version> with the major version installed in your repository. For example:
|
|
||||||
# RUN npm install turbo@2.1.3 --global
|
|
||||||
RUN npm install turbo@2.3.1 --global
|
|
||||||
|
|
||||||
RUN pnpm config set store-dir ~/.pnpm-store
|
|
||||||
|
|
||||||
# 2. Prune projects
|
|
||||||
FROM base AS pruner
|
|
||||||
# https://stackoverflow.com/questions/49681984/how-to-get-version-value-of-package-json-inside-of-dockerfile
|
|
||||||
# RUN export VERSION=$(npm run version)
|
|
||||||
|
|
||||||
ARG PROJECT
|
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# It might be the path to <ROOT> turborepo
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Generate a partial monorepo with a pruned lockfile for a target workspace.
|
|
||||||
# Assuming "@acme/nextjs" is the name entered in the project's package.json: { name: "@acme/nextjs" }
|
|
||||||
RUN turbo prune --scope=${PROJECT} --scope=@kan/db --docker
|
|
||||||
|
|
||||||
# 3. Build the project
|
|
||||||
FROM base AS builder
|
|
||||||
ARG PROJECT
|
|
||||||
|
|
||||||
# Environment to skip .env validation on build
|
|
||||||
ENV CI=true
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy lockfile and package.json's of isolated subworkspace
|
|
||||||
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
|
||||||
COPY --from=pruner /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml
|
|
||||||
COPY --from=pruner /app/out/json/ .
|
|
||||||
|
|
||||||
# First install the dependencies (as they change less often)
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=~/.pnpm-store pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy source code of isolated subworkspace
|
|
||||||
COPY --from=pruner /app/out/full/ .
|
|
||||||
|
|
||||||
|
|
||||||
RUN pnpm build --filter=${PROJECT}
|
|
||||||
|
|
||||||
# Copy static files to standalone directory
|
|
||||||
RUN mkdir -p apps/web/.next/standalone/.next && \
|
|
||||||
mv apps/web/public apps/web/.next/standalone/ && \
|
|
||||||
mv apps/web/.next/static apps/web/.next/standalone/.next/
|
|
||||||
|
|
||||||
# 4. Final image - runner stage to run the application
|
|
||||||
FROM base AS runner
|
|
||||||
ARG APP_DIRNAME
|
|
||||||
|
|
||||||
# Don't run production as root
|
|
||||||
RUN addgroup --system --gid 1001 nodejs
|
|
||||||
RUN adduser --system --uid 1001 nextjs
|
|
||||||
USER nextjs
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
|
|
||||||
COPY --chown=nextjs:nodejs --from=builder /app/ ./
|
|
||||||
WORKDIR /app/apps/${APP_DIRNAME}
|
|
||||||
|
|
||||||
ARG PORT=3000
|
|
||||||
ENV PORT=${PORT}
|
|
||||||
EXPOSE ${PORT}
|
|
||||||
|
|
||||||
CMD ["/bin/sh", "./entrypoint.sh"]
|
|
||||||
@@ -12,5 +12,12 @@ if [ $? -ne 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "\nStarting Next.js application..."
|
echo "\nStarting Next.js application..."
|
||||||
# Start the Next.js application from the web app's directory
|
|
||||||
|
# Check if we should use standalone mode
|
||||||
|
if [ "$NEXT_PUBLIC_USE_STANDALONE_OUTPUT" = "true" ]; then
|
||||||
|
echo "Starting in standalone mode..."
|
||||||
exec node .next/standalone/apps/web/server.js
|
exec node .next/standalone/apps/web/server.js
|
||||||
|
else
|
||||||
|
echo "Starting in standard mode..."
|
||||||
|
exec pnpm start
|
||||||
|
fi
|
||||||
@@ -13,7 +13,7 @@ const config = {
|
|||||||
output:
|
output:
|
||||||
env("NEXT_PUBLIC_USE_STANDALONE_OUTPUT") === "true"
|
env("NEXT_PUBLIC_USE_STANDALONE_OUTPUT") === "true"
|
||||||
? "standalone"
|
? "standalone"
|
||||||
: "export",
|
: undefined,
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
|
||||||
/** Enables hot reloading for local packages without a build step */
|
/** Enables hot reloading for local packages without a build step */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm next build",
|
"build": "pnpm with-env next build",
|
||||||
"clean": "git clean -xdf .cache .next .turbo node_modules",
|
"clean": "git clean -xdf .cache .next .turbo node_modules",
|
||||||
"dev": "pnpm with-env next dev | pino-pretty",
|
"dev": "pnpm with-env next dev | pino-pretty",
|
||||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- dokploy-network
|
- dokploy-network
|
||||||
build:
|
build:
|
||||||
context: .
|
context: ..
|
||||||
dockerfile: ./apps/web/Dockerfile
|
dockerfile: apps/web/Dockerfile
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- NEXT_PUBLIC_KAN_ENV=${NEXT_PUBLIC_KAN_ENV}
|
- NEXT_PUBLIC_KAN_ENV=${NEXT_PUBLIC_KAN_ENV}
|
||||||
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
|
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const sendEmail = async (
|
|||||||
template: Templates,
|
template: Templates,
|
||||||
data: Record<string, string>,
|
data: Record<string, string>,
|
||||||
) => {
|
) => {
|
||||||
|
try {
|
||||||
const EmailTemplate = emailTemplates[template];
|
const EmailTemplate = emailTemplates[template];
|
||||||
|
|
||||||
const html = await render(<EmailTemplate {...data} />, { pretty: true });
|
const html = await render(<EmailTemplate {...data} />, { pretty: true });
|
||||||
@@ -47,4 +48,15 @@ export const sendEmail = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Email sending failed:", {
|
||||||
|
to,
|
||||||
|
from: process.env.EMAIL_FROM,
|
||||||
|
subject,
|
||||||
|
template,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user