diff --git a/.env.example b/.env.example index 2985555c..1ec2c583 100644 --- a/.env.example +++ b/.env.example @@ -10,6 +10,7 @@ # should be updated accordingly. # General +NEXT_TELEMETRY_DISABLED="true" NODE_ENV="development" NEXT_PUBLIC_SITE_URL="http://localhost:3000" @@ -28,8 +29,8 @@ STORAGE_PASSWORD="password" STORAGE_NAME="images" # Auth -FEIDE_CLIENT_ID= -FEIDE_CLIENT_SECRET= +FEIDE_CLIENT_ID=" " +FEIDE_CLIENT_SECRET=" " FEIDE_AUTHORIZATION_ENDPOINT="https://auth.dataporten.no/oauth/authorization" FEIDE_TOKEN_ENDPOINT="https://auth.dataporten.no/oauth/token" FEIDE_USERINFO_ENDPOINT="https://auth.dataporten.no/openid/userinfo" diff --git a/Dockerfile b/Dockerfile index 45c64faa..bcd4f378 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,88 @@ -FROM imbios/bun-node:20-slim +FROM imbios/bun-node:22-slim AS base + +# Install dependencies only when needed +FROM base AS deps WORKDIR /app -COPY package.json bun.lockb ./ +ENV NODE_ENV=production -RUN bun install --production --frozen-lockfile +# Install dependencies +COPY package.json bun.lockb ./ +RUN bun 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 NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 ENV SKIP_ENV_VALIDATION=true + +# Set environment variables during the build +ARG NEXT_PUBLIC_SITE_URL +ARG DATABASE_USER +ARG DATABASE_PASSWORD +ARG DATABASE_HOST +ARG DATABASE_PORT +ARG DATABASE_NAME +ARG STORAGE_HOST +ARG STORAGE_PORT +ARG STORAGE_USER +ARG STORAGE_PASSWORD +ARG STORAGE_NAME +ARG FEIDE_CLIENT_ID +ARG FEIDE_CLIENT_SECRET +ARG FEIDE_AUTHORIZATION_ENDPOINT +ARG FEIDE_TOKEN_ENDPOINT +ARG FEIDE_USERINFO_ENDPOINT + +ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL +ENV DATABASE_USER=$DATABASE_USER +ENV DATABASE_PASSWORD=$DATABASE_PASSWORD +ENV DATABASE_HOST=$DATABASE_HOST +ENV DATABASE_PORT=$DATABASE_PORT +ENV DATABASE_NAME=$DATABASE_NAME +ENV STORAGE_HOST=$STORAGE_HOST +ENV STORAGE_PORT=$STORAGE_PORT +ENV STORAGE_USER=$STORAGE_USER +ENV STORAGE_PASSWORD=$STORAGE_PASSWORD +ENV STORAGE_NAME=$STORAGE_NAME +ENV FEIDE_CLIENT_ID=$FEIDE_CLIENT_ID +ENV FEIDE_CLIENT_SECRET=$FEIDE_CLIENT_SECRET +ENV FEIDE_AUTHORIZATION_ENDPOINT=$FEIDE_AUTHORIZATION_ENDPOINT +ENV FEIDE_TOKEN_ENDPOINT=$FEIDE_TOKEN_ENDPOINT +ENV FEIDE_USERINFO_ENDPOINT=$FEIDE_USERINFO_ENDPOINT + +# Build the application +RUN bunx next build + + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + ENV NODE_ENV=production -RUN bun run build +ENV NEXT_TELEMETRY_DISABLED=1 +ENV SKIP_ENV_VALIDATION=true + +RUN addgroup --system --gid 1002 nodejs && \ + adduser --system --uid 1002 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next && 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 -ENTRYPOINT [ "bun", "run", "start" ] +# server.js is created by next build from the standalone output +CMD ["bun", "run", "server.js"] diff --git a/bun.lockb b/bun.lockb index bf237af4..878935d3 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/docker-compose.yml b/docker-compose.yml index 50e0d20b..dae14ffb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,23 @@ services: build: context: . dockerfile: Dockerfile + args: + - NEXT_PUBLIC_SITE_URL + - DATABASE_HOST + - DATABASE_PORT + - DATABASE_USER + - DATABASE_PASSWORD + - DATABASE_NAME + - STORAGE_HOST + - STORAGE_PORT + - STORAGE_USER + - STORAGE_PASSWORD + - STORAGE_NAME + - FEIDE_CLIENT_ID + - FEIDE_CLIENT_SECRET + - FEIDE_AUTHORIZATION_ENDPOINT + - FEIDE_TOKEN_ENDPOINT + - FEIDE_USERINFO_ENDPOINT ports: - "3000:3000" db: diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 3a6914b2..218af133 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,8 +1,6 @@ -import { env } from '@/env'; - /** @type {import('next-sitemap').IConfig} */ const config = { - siteUrl: env.NEXT_PUBLIC_SITE_URL, + siteUrl: process.env.NEXT_PUBLIC_SITE_URL ?? '', generateRobotsTxt: true, generateIndexSitemap: false, }; diff --git a/next.config.js b/next.config.js index 26cdcc5a..69a418ac 100644 --- a/next.config.js +++ b/next.config.js @@ -8,6 +8,9 @@ await import('./src/env.js'); const withNextIntl = nextIntl('./src/lib/locale/i18n.ts'); /** @type {import("next").NextConfig} */ -const config = {}; +const config = { + reactStrictMode: true, + output: 'standalone', +}; export default withNextIntl(config); diff --git a/package.json b/package.json index 133853de..b15b270e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "prepare": "lefthook install", + "prepare": "if [ \"$NODE_ENV\" != \"production\" ]; then lefthook install; fi", "postbuild": "next-sitemap", "prebuild": "next telemetry disable", "build": "next build", diff --git a/src/server/s3/index.ts b/src/server/s3/index.ts index de41152e..57ff7420 100644 --- a/src/server/s3/index.ts +++ b/src/server/s3/index.ts @@ -27,6 +27,6 @@ const s3 = if (env.NODE_ENV !== 'production') globalForS3.s3 = s3; const buckets = env.STORAGE_NAME.split(','); -const imageBucket = buckets[0] as string; +const imageBucket = buckets[0]; export { s3, endpoint, imageBucket, PutObjectCommand, DeleteObjectCommand };