Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# Build the operator console, then serve the built assets. The previous image ran `vite dev` as
|
||||
# root with the whole source tree inside it, which is a development server rather than a release
|
||||
# artefact: it rebuilds on request, exposes the module graph and needs write access to its own
|
||||
# source. M16 replaces it with a static build served by an unprivileged nginx.
|
||||
FROM node:22-alpine@sha256:c610fcdfb1d5b4740dd70c284ed3cb16bb857e0f7166196e36a5501df7a3aa32 AS build
|
||||
WORKDIR /app
|
||||
RUN apk upgrade --no-cache
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
|
||||
# Vite inlines its VITE_* variables at build time, so the API base URL is a build argument rather
|
||||
# than a runtime one. The default matches the standard local deployment.
|
||||
ARG VITE_API_BASE_URL=http://localhost:8000
|
||||
ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:1.29-alpine@sha256:0c79d56aee561a1d81c63f00eee5fb5fe29279560cdc55e91425133104c7fbe6
|
||||
USER root
|
||||
RUN apk upgrade --no-cache
|
||||
ARG VITE_API_BASE_URL=http://localhost:8000
|
||||
ARG MODELFORGE_VERSION=0.0.0
|
||||
ARG MODELFORGE_COMMIT=""
|
||||
ARG MODELFORGE_BUILT_AT=""
|
||||
ENV MODELFORGE_BUILD_COMMIT=${MODELFORGE_COMMIT}
|
||||
ENV MODELFORGE_BUILD_TIMESTAMP=${MODELFORGE_BUILT_AT}
|
||||
LABEL org.opencontainers.image.title="ITWorx ModelForge operator console"
|
||||
LABEL org.opencontainers.image.description="Operator console for the ITWorx ModelForge control plane"
|
||||
LABEL org.opencontainers.image.version="${MODELFORGE_VERSION}"
|
||||
LABEL org.opencontainers.image.revision="${MODELFORGE_COMMIT}"
|
||||
LABEL org.opencontainers.image.created="${MODELFORGE_BUILT_AT}"
|
||||
LABEL org.opencontainers.image.source="https://git.example.com/example/modelforge.git"
|
||||
LABEL org.opencontainers.image.vendor="ITWorx"
|
||||
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
|
||||
|
||||
# The runtime listens above 1024 and returns to the image's unprivileged nginx user after the
|
||||
# signed package upgrade and immutable file assembly. It works with a read-only root filesystem
|
||||
# plus a tmpfs for its caches.
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY security-headers.inc.template /etc/nginx/security-headers.inc.template
|
||||
|
||||
# The bundle's API origin is compiled in at build time, so the connect-src that protects it is
|
||||
# derived from the same argument rather than maintained separately and allowed to drift. Only the
|
||||
# origin is used; a path in connect-src is ignored by the browser anyway. The final grep makes a
|
||||
# failed substitution break the build instead of shipping a policy with a placeholder in it.
|
||||
RUN set -eu; \
|
||||
API_ORIGIN=$(printf '%s' "${VITE_API_BASE_URL}" | cut -d/ -f1-3); \
|
||||
sed "s|__API_ORIGIN__|${API_ORIGIN}|" /etc/nginx/security-headers.inc.template \
|
||||
> /etc/nginx/conf.d/security-headers.inc; \
|
||||
rm /etc/nginx/security-headers.inc.template; \
|
||||
grep -q "connect-src 'self' ${API_ORIGIN};" /etc/nginx/conf.d/security-headers.inc
|
||||
USER nginx
|
||||
|
||||
EXPOSE 3000
|
||||
HEALTHCHECK --interval=15s --timeout=3s --retries=5 \
|
||||
CMD wget -q -O /dev/null http://127.0.0.1:3000/ || exit 1
|
||||
Reference in New Issue
Block a user