Portal app-shell as a busybox target, git without perl, quieter first start
Docs / docs (push) Successful in 28s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m44s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m34s
pre-commit / pre-commit (push) Failing after 2m29s
Test Backend / test-backend (3.12) (push) Successful in 4m32s
Test Backend / test-backend (3.14) (push) Successful in 4m15s
Compose Smoke Test / test-compose (push) Successful in 37s
Playwright Tests / merge-reports (push) Successful in 1m33s
Docs / docs (push) Successful in 28s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m44s
Playwright Tests / test-playwright (2, 2) (push) Successful in 2m34s
pre-commit / pre-commit (push) Failing after 2m29s
Test Backend / test-backend (3.12) (push) Successful in 4m32s
Test Backend / test-backend (3.14) (push) Successful in 4m15s
Compose Smoke Test / test-compose (push) Successful in 37s
Playwright Tests / merge-reports (push) Successful in 1m33s
The portal's copy of the dashboard is the `appshell` target of backend/Dockerfile (18 MB instead of the 252 MB nginx image); the nginx frontend Dockerfile, its confs and csp.check.ts are gone, since the app and the hub both hash the CSP from the index.html they serve. The runtime image copies the 4 MB git binary alone: the store's init, add, commit, gc and rev-parse are builtins, and a build-time round trip fails the build if that ever changes. About 100 MB of perl and helpers less. The bundled Redis's overcommit warning and FastMCP's lifespan warning no longer greet every `docker logs`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+31
-6
@@ -20,6 +20,8 @@ COPY ./frontend /app/frontend
|
||||
# Empty: the dashboard calls the API as a path on whichever origin served it,
|
||||
# so one build works behind any port, hostname or proxy.
|
||||
ENV VITE_API_URL=
|
||||
# Set only for the copy the portal serves (the appshell stage below).
|
||||
ARG VITE_BASE
|
||||
RUN bun run build
|
||||
|
||||
# ── Python environment ───────────────────────────────────────────
|
||||
@@ -69,16 +71,39 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
&& uv pip install --python /app/.venv/bin/python /tmp/connector-wheels/*.whl \
|
||||
|| echo "no connectors bundled"'
|
||||
|
||||
# ── The portal's copy of the dashboard ──────────────────────────
|
||||
# The hub serves the dashboard for every instance it tunnels to, from
|
||||
# /app-shell/. index/docker/compose.yml builds this target with
|
||||
# VITE_BASE=/app-shell/ and copies /dist into the hub's volume.
|
||||
FROM busybox:1.37 AS appshell
|
||||
COPY --from=frontend /app/frontend/dist /dist
|
||||
|
||||
# ── git, without perl ────────────────────────────────────────────
|
||||
# The flow store runs init, add, commit, gc and rev-parse, all built into the
|
||||
# one binary, which needs nothing slim lacks. Debian's package would bring
|
||||
# perl and the remote helpers along, about 100 MB nothing here calls.
|
||||
FROM python:3.13-slim AS git
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ── Runtime ──────────────────────────────────────────────────────
|
||||
FROM python:3.13-slim
|
||||
|
||||
# git versions the flows. redis-server keeps message state when no external
|
||||
# Redis is named. tini reaps the python node workers that outlive their pool,
|
||||
# which would otherwise pile up as zombies under PID 1. procps is uptime, ps
|
||||
# and free for Command nodes, the demo's among them.
|
||||
COPY --from=git /usr/bin/git /usr/bin/git
|
||||
|
||||
# redis-server keeps message state when no external Redis is named. tini reaps
|
||||
# the python node workers that outlive their pool, which would otherwise pile
|
||||
# up as zombies under PID 1. procps is uptime, ps and free for Command nodes,
|
||||
# the demo's among them. The git round trip fails the build if the binary
|
||||
# above ever needs something this image does not have.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends git procps redis-server tini \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
&& apt-get install -y --no-install-recommends procps redis-server tini \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& git init -q /tmp/g 2>/dev/null \
|
||||
&& git -C /tmp/g -c user.name=x -c user.email=x@x commit -q --allow-empty -m x \
|
||||
&& git -C /tmp/g gc --quiet && git -C /tmp/g rev-parse HEAD >/dev/null \
|
||||
&& rm -rf /tmp/g
|
||||
|
||||
# /app/.venv holds the app and nothing of anybody else's, so there is nothing
|
||||
# here to adopt: node code gets a venv of its own on the data volume, which is
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
# so without it a restart forgets all three. In the background on purpose: its
|
||||
# appendonly file is written on every change, so the SIGKILL it gets when the
|
||||
# container stops loses nothing that was acknowledged.
|
||||
#
|
||||
# Its memory-overcommit warning is dropped: the setting is the host kernel's,
|
||||
# nothing in a container can change it, and it only matters to a fork for a
|
||||
# snapshot under memory pressure. Every other warning still reaches the log.
|
||||
set -e
|
||||
|
||||
if [ -z "$REDIS_HOST" ]; then
|
||||
mkdir -p /data/redis
|
||||
redis-server --bind 127.0.0.1 --port 6379 --dir /data/redis \
|
||||
--appendonly yes --loglevel warning &
|
||||
--appendonly yes --loglevel warning \
|
||||
| grep --line-buffered -v "Memory overcommit must be enabled" &
|
||||
i=0
|
||||
until redis-cli -h 127.0.0.1 ping >/dev/null 2>&1; do
|
||||
i=$((i + 1))
|
||||
|
||||
@@ -13,6 +13,7 @@ identity rather than some service account.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
from contextvars import ContextVar
|
||||
from typing import Any
|
||||
|
||||
@@ -24,7 +25,12 @@ from fluksio.sdk.client import seg as _seg
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
mcp = FastMCP("fluksio")
|
||||
# FastMCP's own settings model leaves `lifespan` a forward reference, which
|
||||
# pydantic-settings warns about on every start. Nothing reads that field from
|
||||
# the environment, so the warning says nothing about this app.
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", message="Field 'lifespan' has an incomplete")
|
||||
mcp = FastMCP("fluksio")
|
||||
|
||||
#: The tool calls never leave the process, so the host is a label, not a route.
|
||||
_INTERNAL_BASE = "http://fluksio-mcp.internal"
|
||||
|
||||
Reference in New Issue
Block a user