Summary
The official ghcr.io/eyeix/meilisearch-ui Docker image runs pnpm run build at container start (see scripts/cmd.sh), so every pod restart spends 2β5 min on a production Vite build before serving traffic. In a Kubernetes rolling update with the standard maxUnavailable: 0 strategy this blocks the rollout for the full build duration on every replica.
Root cause: the singleton-mode runtime config is read from VITE_SINGLETON_* env vars, which Vite resolves at build time, not runtime. The image therefore can't ship a pre-built bundle today without also shipping a way to inject the runtime values into the static assets after the build.
Repro
docker run --rm \
-e SINGLETON_MODE=true \
-e SINGLETON_HOST=https://demo.meilisearch.example \
-e SINGLETON_API_KEY=test \
-p 24900:24900 \
ghcr.io/eyeix/meilisearch-ui:0.15.1
Observe vite vX.x building for production... taking 2β5 min on a 500m-CPU Kubernetes pod (or 30β60s on a developer laptop). vite preview only starts after the build finishes.
Impact
- Cold start latency: pod is not Ready for 2β5 min; readiness probes must be tuned to a 5β10 min
startupProbe.failureThreshold to survive. We use failureThreshold: 60 with periodSeconds: 10.
- Rolling-update lockstep:
maxUnavailable: 0 blocks the old pod from terminating until the new one passes its build, doubling pod resource use for that window.
- Key rotation: any secret rotation (Stakater Reloader, manual
kubectl rollout restart) triggers a fresh 2β5 min build.
Suggested fix
Two equivalent approaches, both common in Vite-served apps:
- Placeholder string-replacement at container start. Bake the bundle once at image-build time with sentinel placeholders (e.g.
__MEILI_SINGLETON_HOST__, __MEILI_SINGLETON_API_KEY__), then sed -i over dist/assets/*.{js,css} in the entrypoint to replace them with the runtime env values before vite preview. Boot time drops to O(seconds). PR with this approach attached.
- Runtime config endpoint. Ship
dist/config.js that exports window.__MEILI_UI_CONFIG__, populate it from env in the entrypoint, and have the app read from window instead of import.meta.env. Avoids touching the bundled JS at all.
(1) is the minimal-diff option and what most Docker-deployed Vite apps do β opened a draft PR with that approach: #270.
Workaround
Until upstream lands a fix we patch the entrypoint downstream. Removing the workaround will be a one-line image-tag bump.
Environment
- Image:
ghcr.io/eyeix/meilisearch-ui:0.15.1
- Vite:
6.x (per build log)
- Runtime: GKE Autopilot, 500m CPU / 2 Gi mem container
- Workload: Deployment with
replicas: 1, maxUnavailable: 0
Happy to iterate on the PR if a different approach is preferred.
Summary
The official
ghcr.io/eyeix/meilisearch-uiDocker image runspnpm run buildat container start (seescripts/cmd.sh), so every pod restart spends 2β5 min on a production Vite build before serving traffic. In a Kubernetes rolling update with the standardmaxUnavailable: 0strategy this blocks the rollout for the full build duration on every replica.Root cause: the singleton-mode runtime config is read from
VITE_SINGLETON_*env vars, which Vite resolves at build time, not runtime. The image therefore can't ship a pre-built bundle today without also shipping a way to inject the runtime values into the static assets after the build.Repro
Observe
vite vX.x building for production...taking 2β5 min on a 500m-CPU Kubernetes pod (or 30β60s on a developer laptop).vite previewonly starts after the build finishes.Impact
startupProbe.failureThresholdto survive. We usefailureThreshold: 60withperiodSeconds: 10.maxUnavailable: 0blocks the old pod from terminating until the new one passes its build, doubling pod resource use for that window.kubectl rollout restart) triggers a fresh 2β5 min build.Suggested fix
Two equivalent approaches, both common in Vite-served apps:
__MEILI_SINGLETON_HOST__,__MEILI_SINGLETON_API_KEY__), thensed -ioverdist/assets/*.{js,css}in the entrypoint to replace them with the runtime env values beforevite preview. Boot time drops to O(seconds). PR with this approach attached.dist/config.jsthat exportswindow.__MEILI_UI_CONFIG__, populate it from env in the entrypoint, and have the app read fromwindowinstead ofimport.meta.env. Avoids touching the bundled JS at all.(1) is the minimal-diff option and what most Docker-deployed Vite apps do β opened a draft PR with that approach: #270.
Workaround
Until upstream lands a fix we patch the entrypoint downstream. Removing the workaround will be a one-line image-tag bump.
Environment
ghcr.io/eyeix/meilisearch-ui:0.15.16.x(per build log)replicas: 1,maxUnavailable: 0Happy to iterate on the PR if a different approach is preferred.