feat(cloud-api): bake cloud-console SPA into the image and serve at /console
Multi-stage Dockerfile: stage 1 (node:20-bookworm-slim) builds cloud-console with vite base "/console/"; stage 2 (uv) copies dist/ to /app/console-static. Cloud API mounts the SPA at /console via SpaStaticFiles (StaticFiles subclass that falls back to index.html for deep-link refreshes) when the new CLOUD_CONSOLE_STATIC_DIR env is set, and 307-redirects / to /console/. Static files bypass bearer auth (the SPA shell is public; tokens are still required for /v1/*). Compose enables the mount by default; local dev still uses npm run dev + CLOUD_CONSOLE_CORS_ORIGINS. Jenkinsfile passes mirror overrides (NODE_IMAGE, NPM_REGISTRY, UV_IMAGE, APT_MIRROR, UV_INDEX_URL) as --build-arg, defaulting to CN mirrors (registry.jerryyan.net, registry.npmmirror.com, registry-ghcr.jerryyan.top, mirrors.aliyun.com) so CN builds don't time out; Dockerfile ARGs default to official upstreams so `docker build .` still works anywhere. Backend suite: 443 passed (-m "not integration"); cloud-console typecheck and production build succeed with the new base path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+47
-2
@@ -1,4 +1,33 @@
|
||||
FROM ghcr.io/astral-sh/uv:python3.14-bookworm-slim
|
||||
# syntax=docker/dockerfile:1
|
||||
#
|
||||
# Build args let CI inject mirrors for faster builds in CN networks; the
|
||||
# defaults keep the Dockerfile portable so anyone can `docker build .`
|
||||
# without extra configuration.
|
||||
#
|
||||
# NODE_IMAGE – stage 1 base (Docker Hub library/node)
|
||||
# NPM_REGISTRY – npm registry for `npm ci`
|
||||
# UV_IMAGE – stage 2 base (ghcr.io/astral-sh/uv)
|
||||
# APT_MIRROR – Debian apt mirror host (e.g. mirrors.aliyun.com); empty = official
|
||||
# UV_INDEX_URL – PyPI index URL passed through to `uv sync`; empty = official
|
||||
|
||||
# Stage 1: build the cloud-console Vue 3 SPA.
|
||||
# NOTE: do not set NODE_ENV=production here — vue-tsc and typescript are
|
||||
# devDependencies required by `npm run build`.
|
||||
ARG NODE_IMAGE=node:20-bookworm-slim
|
||||
ARG NPM_REGISTRY=https://registry.npmjs.org
|
||||
FROM ${NODE_IMAGE} AS frontend
|
||||
# Re-declare inside the stage so --build-arg values (or the global default)
|
||||
# are visible to RUN. Without this, ARGs declared before FROM are inaccessible.
|
||||
ARG NPM_REGISTRY
|
||||
WORKDIR /app
|
||||
COPY cloud-console/package.json cloud-console/package-lock.json ./
|
||||
RUN npm ci --registry=${NPM_REGISTRY}
|
||||
COPY cloud-console/ ./
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: the existing Python image, now carrying the SPA build output.
|
||||
ARG UV_IMAGE=ghcr.io/astral-sh/uv:python3.14-bookworm-slim
|
||||
FROM ${UV_IMAGE}
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
@@ -7,10 +36,26 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends curl \
|
||||
ARG APT_MIRROR=
|
||||
# bookworm uses /etc/apt/sources.list.d/debian.sources (DEB822 format); older
|
||||
# Debian releases use /etc/apt/sources.list. Patch whichever exists.
|
||||
RUN if [ -n "$APT_MIRROR" ]; then \
|
||||
if [ -f /etc/apt/sources.list.d/debian.sources ]; then \
|
||||
sed -i "s|deb.debian.org|$APT_MIRROR|g; s|security.debian.org|$APT_MIRROR|g" \
|
||||
/etc/apt/sources.list.d/debian.sources; \
|
||||
elif [ -f /etc/apt/sources.list ]; then \
|
||||
sed -i "s|deb.debian.org|$APT_MIRROR|g; s|security.debian.org|$APT_MIRROR|g" \
|
||||
/etc/apt/sources.list; \
|
||||
fi; \
|
||||
fi \
|
||||
&& apt-get update && apt-get install -y --no-install-recommends curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=frontend /app/dist /app/console-static
|
||||
COPY . .
|
||||
|
||||
ARG UV_INDEX_URL=
|
||||
ENV UV_INDEX_URL=${UV_INDEX_URL}
|
||||
RUN uv sync --locked --all-packages --no-dev
|
||||
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
Reference in New Issue
Block a user