diff --git a/.dockerignore b/.dockerignore index c29b6573..0050cdd1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,18 @@ -Containerfile -.dockerignore -node_modules -npm-debug.log -README.md -.next -.git +# ignore everything by default +** + +# allow JS files +!*.ts +!*.js +!*.mjs +!*.json +!pnpm-*.yaml + +# nextjs files +!public/ +!src/ +!styles/ +!scripts/ + +# custom build dir for standalone output +!out/ diff --git a/Containerfile b/Containerfile index 040ce594..8066bbee 100644 --- a/Containerfile +++ b/Containerfile @@ -1,72 +1,34 @@ -# Mostly boilerplate image spec, taken from nextjs docs: -# https://nextjs.org/docs/pages/building-your-application/deploying#docker-image +# Extremely simple Containerfile, inappropriately using `pnpm run dev` +# as the entrypoint, due to https://github.com/penumbra-zone/dex-explorer/issues/73. +# Longer-term we should fix the app's config api, and return to using a prod build, +# as described in https://nextjs.org/docs/pages/building-your-application/deploying#docker-image. -# Provide specific arg for setting the version of nodejs to use. -# Should match what's in .nvmrc for development. -ARG NODE_MAJOR_VERSION=18.20 -FROM docker.io/node:${NODE_MAJOR_VERSION}-alpine AS base -# Install dependencies only when needed -FROM base AS deps -# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. -RUN apk add --no-cache libc6-compat -WORKDIR /app - -# Install dependencies -COPY package.json pnpm-lock.yaml* ./ -RUN corepack enable pnpm && pnpm 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 . . - -# Next.js collects completely anonymous telemetry data about general usage. -# Learn more here: https://nextjs.org/telemetry -ENV NEXT_TELEMETRY_DISABLED 1 - -# Build the website as standalone output. -RUN npm --version && node --version -RUN npm run build - -# Production image, copy all the files and run next -FROM base AS runner +FROM docker.io/node:20-slim AS builder LABEL maintainer="team@penumbralabs.xyz" -WORKDIR /app - -ENV NODE_ENV production ENV NEXT_TELEMETRY_DISABLED 1 # Create normal user for app -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs -# Set the correct permission for prerender cache -RUN mkdir .next -RUN chown nextjs:nodejs .next -COPY --from=builder /app/public ./public +ARG GID=1001 +ARG UID=1001 +ARG USERNAME=nextjs +ARG GROUPNAME=nodejs +RUN groupadd -g ${GID} ${GROUPNAME} \ + && useradd -l -m -d /home/${USERNAME} -g ${GID} -u ${UID} ${USERNAME} + +# Enable `pnpm` so we can use it instead of `npm` in builds. +RUN corepack enable pnpm +WORKDIR /app +RUN chown -R ${USERNAME}:${GROUPNAME} /app +USER nextjs -# Automatically leverage output traces to reduce image size -# https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# Install node dependencies only when needed +COPY --chown=${UID}:${GID} package.json pnpm-lock.yaml* ./ +RUN pnpm install --frozen-lockfile -# Hack to add a semblance of logging to the nextjs server-side node instance, -# so that all route GETs are logged, which adds much-needed context when exceptions -# are thrown. Exceptions still log a full stack trace, rather than a succinct -# error message, but it's a start! -# -# Why this hack is necessary is beyond my ken. I assume it's an upsell attempt -# at hosting on a sass platform like vercel. Source: -# https://gist.github.com/x-yuri/f4a2f1363ae5c08981c257cc406e00ac -RUN sed -Ei \ - -e '/await requestHandler/iconst __start = new Date;' \ - -e '/await requestHandler/aconsole.log(`-- [${__start.toISOString()}] ${((new Date - __start) / 1000).toFixed(3)} ${req.method} ${req.url}`);' \ - node_modules/next/dist/server/lib/start-server.js +# Rebuild the source code only when needed +COPY --chown=${UID}:${GID} . . -USER nextjs EXPOSE 3000 -ENV PORT 3000 +ENV HOSTNAME="0.0.0.0" -# server.js is created by next build from the standalone output -# https://nextjs.org/docs/pages/api-reference/next-config-js/output -CMD HOSTNAME="0.0.0.0" node server.js +CMD ["pnpm", "run", "dev"] diff --git a/justfile b/justfile index b8bf229c..24726259 100644 --- a/justfile +++ b/justfile @@ -8,4 +8,23 @@ dev: # build container image container: - podman build -f Containerfile . + podman build -t penumbra-dex-explorer -f Containerfile . + +# run container image +run-container: container + podman run -it \ + -e PENUMBRA_GRPC_ENDPOINT \ + -e PENUMBRA_INDEXER_ENDPOINT \ + -e NEXT_PUBLIC_CHAIN_ID \ + -e PENUMBRA_INDEXER_CA_CERT \ + -p 3000:3000 \ + penumbra-dex-explorer + +# build the standalone output locally. +manual-build: + rm -rf .next/ out/ + pnpm run build + rsync -a .next/standalone/ out/ + rsync -a .next/static/ out/.next/static/ + rsync -a public/ out/public/ + # cd out/ && HOSTNAME=0.0.0.0 node server.js