initial commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
###############################################################################
|
||||
# SHARP-ER web - React Router 8 (framework mode, SSR) on Node 22
|
||||
#
|
||||
# Adapted from the React Router template Dockerfile. Two things changed:
|
||||
# * npm -> pnpm, because this repository is a pnpm workspace and there is no
|
||||
# package-lock.json to `npm ci` from;
|
||||
# * the build context is the REPOSITORY ROOT, where pnpm-lock.yaml,
|
||||
# pnpm-workspace.yaml and .npmrc live.
|
||||
#
|
||||
# docker build -f apps/web/Dockerfile -t sharper-web .
|
||||
# docker compose build web # does exactly that
|
||||
#
|
||||
# The server reads STRAPI_URL / STRAPI_TOKEN / SITE_URL at RUN time, never at
|
||||
# build time, so one image is valid for every environment.
|
||||
###############################################################################
|
||||
|
||||
# --- base: the toolchain both stages share ----------------------------------
|
||||
FROM node:22-bookworm-slim AS base
|
||||
ENV PNPM_VERSION=9.12.3
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& npm install --global "pnpm@${PNPM_VERSION}"
|
||||
WORKDIR /repo
|
||||
|
||||
|
||||
# --- build: install dependencies and produce build/client + build/server -----
|
||||
FROM base AS build
|
||||
|
||||
# Manifests first so the install layer stays cached. Both workspace manifests
|
||||
# are copied: pnpm checks the lockfile against every project in the workspace
|
||||
# and treats it as stale if one is missing.
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
|
||||
COPY apps/web/package.json ./apps/web/
|
||||
COPY apps/cms/package.json ./apps/cms/
|
||||
|
||||
# `--filter web...` keeps Strapi out of this image entirely.
|
||||
# devDependencies are required: vite, @react-router/dev and tailwind build here.
|
||||
RUN pnpm install --frozen-lockfile --filter web...
|
||||
|
||||
COPY apps/web ./apps/web
|
||||
RUN pnpm --filter web build
|
||||
|
||||
|
||||
# --- runtime ----------------------------------------------------------------
|
||||
FROM base AS runtime
|
||||
|
||||
ENV NODE_ENV=production \
|
||||
PORT=3000
|
||||
|
||||
COPY --from=build /repo/node_modules ./node_modules
|
||||
COPY --from=build /repo/package.json /repo/pnpm-workspace.yaml /repo/.npmrc ./
|
||||
COPY --from=build /repo/apps/web ./apps/web
|
||||
|
||||
RUN chown -R node:node /repo/apps/web
|
||||
USER node
|
||||
WORKDIR /repo/apps/web
|
||||
EXPOSE 3000
|
||||
|
||||
# /en is a real page: it proves the SSR handler renders, not just that a socket
|
||||
# is open. It stays 200 even when the CMS is unreachable, because every route
|
||||
# falls back to its bundled draft copy - so this healthcheck tracks the web
|
||||
# service alone.
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=5 \
|
||||
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/en').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
||||
|
||||
# react-router-serve, the production server that ships with the framework.
|
||||
CMD ["pnpm", "start"]
|
||||
Reference in New Issue
Block a user