Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: use dev runtime for container image #76

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -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/
86 changes: 24 additions & 62 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -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="[email protected]"
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"]
21 changes: 20 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading