A New Collection of Thoughtful Learning Apps — Now Available on iOS & Android

Image
I’m excited to share a set of mobile apps I’ve recently completed and published on both the Google Play Store and the Apple App Store. These apps are designed with a simple goal in mind: to make meaningful, structured content more accessible, whether you’re studying theology or improving your English vocabulary. 📱 Now Available on Both Platforms All apps are live and available for download: Google Play Developer Page: https://play.google.com/store/apps/dev?id=5835943159853189043 Apple App Store Developer Page: https://apps.apple.com/ca/developer/q-z-l-corp/id1888794100 📖 Theology & Confession Study Apps For those interested in Reformed theology and classical Christian teachings, I’ve developed a series of apps that present foundational texts in a clean, focused reading format: The Belgic Confession Canons of Dort Heidelberg Catechism Westminster Shorter Catechism Each app is designed to provide a distraction-free experience, making it easier to read, reflect, and revisit these im...

Building a Minimal Docker Image for Next.js Standalone Apps

Building a Minimal Docker Image for Next.js Standalone Apps

This is Part 2 of the series: Self-Hosting Next.js in Kubernetes (Without Vercel).

In Part 1, we covered how to run a Next.js app in standalone mode. Now let’s improve the deployment by building a clean, minimal Docker image that works well in Kubernetes and OpenShift.




Why Multi-Stage Docker Builds Matter

A common mistake is shipping your entire source tree and development dependencies into production.

A multi-stage Docker build allows you to:

  • Keep build tools out of production
  • Reduce image size significantly
  • Improve security
  • Speed up CI and deployments

For Next.js standalone apps, this pattern works extremely well.


Stage 1: Builder Image

The builder stage installs dependencies and runs the normal Next.js build. Nothing special happens here.

FROM node:22-alpine AS builder

WORKDIR /build

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

At this point, Next.js produces:

  • .next/standalone
  • .next/static
  • public

Stage 2: Prepare Standalone Assets

Standalone mode does not automatically include static assets. We must copy them manually.

RUN cp -R dist/apps/example-web/.next/static \
  dist/apps/example-web/.next/standalone/dist/apps/example-web/.next/static

RUN cp -R dist/apps/example-web/public \
  dist/apps/example-web/.next/standalone/apps/example-web/public

This ensures:

  • /_next/static is served correctly
  • /public assets work as expected

Stage 3: Runtime Image

Now we copy only what we need into a lightweight runtime image.

FROM image-registry.openshift-image-registry.svc:5000/internal/nodejs-runtime:22

WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

USER root
COPY --from=builder /build/dist/apps/example-web/.next/standalone ./

RUN chown -R 1001:0 /app && chmod -R g+rwx /app

USER 1001

EXPOSE 3000
ENV PORT=3000

CMD NODE_EXTRA_CA_CERTS=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \
node apps/example-web/server.js

What This Image Contains (and What It Doesn’t)

Included:

  • Minimal Node.js runtime
  • Standalone Next.js server
  • Required dependencies only

Excluded:

  • Source code
  • Dev dependencies
  • Build tools
  • Unused node_modules

This is exactly what you want in production.


Why This Works Well in OpenShift

  • Runs as a non-root user
  • Compatible with restricted SCCs
  • No writable root filesystem required
  • Predictable startup behavior

It also works the same way in:

  • Vanilla Kubernetes
  • Private clusters
  • On-prem environments

Series Progress

Self-Hosting Next.js in Kubernetes (Without Vercel)


Final Thoughts

Standalone mode is only half the story. A clean Docker image is what makes Next.js production-ready in Kubernetes.

In the next post, we’ll wire this image into a real OpenShift deployment using Deployment, Service, and Route objects.

❤️ Support This Blog


If this post helped you, you can support my writing with a small donation. Thank you for reading.


Comments

Popular Posts

2026 Begins: Choosing to Stay on the Path as a Blogger

A New Collection of Thoughtful Learning Apps — Now Available on iOS & Android