mirror of
https://github.com/hanzoai/bootnode.git
synced 2026-10-25 02:31:30 +00:00
Names the two halves for what they are. The repo already holds both (12407e9 merged bootnode/bootnode into this history); this makes the frontend directory say so, so the layout reads the way the owner describes the system: backend and frontend separate, one repo. git mv throughout — 187 renames, history preserved. Every path reference follows: hanzo.yml build context and dockerfile, compose.yml, compose.prod.yml, start.sh, LLM.md, infra/k8s/web-deployments.yaml, infra/cloud/deploy.sh, and the Dockerfile's own COPY paths. Image and container names (bootnode-web, the -web tag suffix) are deliberately NOT renamed here: those are a deploy contract the App CR and ingress bind to on port 3001, and breaking them is a separate, staged change. Console builds green after the move; the Go tree builds. Co-authored-by: Hanzo Dev <[email protected]>
75 lines
3.7 KiB
Docker
75 lines
3.7 KiB
Docker
# Bootnode web console — image ghcr.io/hanzoai/bootnode:<tag>-web.
|
|
#
|
|
# Serves the Next.js STATIC EXPORT via ghcr.io/hanzoai/static, matching the
|
|
# house pattern (hanzo.ai/Dockerfile.production). No nginx, no caddy, no Node
|
|
# server in the runtime image.
|
|
#
|
|
# This file previously ended in a `node server.js` runner copying
|
|
# /app/.next/standalone, but next.config.ts declares `output: "export"`, which
|
|
# emits ./out and NEVER emits .next/standalone. The two deploy models are
|
|
# mutually exclusive, so the image build had been failing at
|
|
# COPY /app/.next/standalone: not found
|
|
# and the deployed image stayed frozen at its last pre-`export` build. One
|
|
# model now: static export, served by hanzoai/static.
|
|
#
|
|
# Build (BuildKit, on-cluster — no GHA). The build context is this directory,
|
|
# so pass the subdir in the git ref:
|
|
# --opt=context=https://github.com/hanzoai/bootnode.git#<SHA>:web
|
|
# --opt=filename=Dockerfile
|
|
# --output=type=image,name=ghcr.io/hanzoai/bootnode:<tag>-web,push=true
|
|
|
|
# ---- build stage: Next.js static export ----------------------------------
|
|
# Node 24 = Active LTS (26 is Current, not LTS). Digest-pinned so the base
|
|
# cannot drift the way the unpinned pnpm did. pnpm 11 requires Node >= 22.
|
|
FROM node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd AS build
|
|
WORKDIR /app
|
|
RUN apk add --no-cache libc6-compat
|
|
|
|
# pnpm-workspace.yaml carries the pnpm settings (allowBuilds) that pnpm >= 11 no
|
|
# longer reads from package.json, and .npmrc is auth/registry only under 11. It
|
|
# must land before install or sharp's build script is skipped and the install
|
|
# fails ERR_PNPM_IGNORED_BUILDS. package.json's `packageManager` pins which pnpm
|
|
# corepack fetches, so a newly published pnpm can never change this build.
|
|
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./
|
|
RUN corepack enable pnpm && pnpm install --frozen-lockfile
|
|
|
|
COPY . .
|
|
|
|
# ONE image, every brand — and therefore NO brand build args.
|
|
#
|
|
# Brand, theme, API origin, IAM issuer and OIDC client are all resolved from
|
|
# window.location.hostname at runtime (console/lib/brand.ts). This image is
|
|
# byte-identical for bootno.de, web3.hanzo.ai, lux.cloud, zoo.cloud and
|
|
# cloud.zoo.network.
|
|
#
|
|
# What used to be here — ARG/ENV NEXT_PUBLIC_BRAND, _API_URL, _WS_URL — could
|
|
# not express that. NEXT_PUBLIC_* is inlined into the client bundle at build
|
|
# time, so each value is one global shared by every host the image serves;
|
|
# picking `bootnode` made the image wrong for the other four. It was also
|
|
# inert: the runtime stage is the Go hanzoai/static binary serving a static
|
|
# export, which never reads container env at all, so the deployment manifests
|
|
# that set these had no effect on the shipped bundle whatsoever.
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
|
|
RUN pnpm run build
|
|
|
|
# Clean URLs on hanzoai/static. The Next export is FLAT (out/pricing.html, …).
|
|
# static serves a *directory's* index.html, and in --spa mode a MISS on an
|
|
# extensionless /pricing falls through to index.html — i.e. every deep page
|
|
# would render the homepage. Materialize a directory index per page so
|
|
# root.Open("/pricing") finds a directory and serves the real page; the flat
|
|
# .html files stay, so /pricing and /pricing.html both work.
|
|
RUN cd out && for f in $(find . -type f -name '*.html' ! -name 'index.html' ! -name '404.html'); do \
|
|
d="${f%.html}"; mkdir -p "$d"; cp "$f" "$d/index.html"; \
|
|
done
|
|
|
|
# ---- serve stage: hanzoai/static (scratch + single Go binary) -------------
|
|
# Port 3001 keeps the existing contract: the bootnode-web App CR declares
|
|
# containerPort/servicePort 3001 and the hand-made bootnode-web-ingress routes
|
|
# to bootnode-web:3001 by number.
|
|
FROM ghcr.io/hanzoai/static:v0.5.1
|
|
COPY --from=build /app/out /srv
|
|
EXPOSE 3001
|
|
ENTRYPOINT ["/static"]
|
|
CMD ["--root=/srv", "--spa", "--port=3001"]
|