# Nexus 6.0 鈥?production image (frontend build + API) # Build: docker compose -f docker/docker-compose.prod.yml build # See: docs/design/plans/2026-06-04-1panel-docker-production.md # 鈹€鈹€ Stage 1: Vue/Vite SPA 鈹€鈹€ FROM node:20-bookworm-slim AS frontend WORKDIR /build/frontend COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci --ignore-scripts COPY frontend/ ./ RUN npx vite build # Stage 1b: React/Vite App V2 FROM node:20-bookworm-slim AS frontend_v2 WORKDIR /build/frontend-v2 COPY frontend-v2/package.json frontend-v2/package-lock.json* ./ RUN if [ -f package-lock.json ]; then npm ci --ignore-scripts; else npm install --ignore-scripts; fi COPY frontend-v2/ ./ RUN npx vite build # 鈹€鈹€ Stage 2: Python API + built static assets 鈹€鈹€ FROM python:3.12-slim-bookworm RUN apt-get update \ && apt-get install -y --no-install-recommends \ curl \ openssh-client \ rsync \ sshpass \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY server/ ./server/ COPY web/agent/ ./web/agent/ COPY --from=frontend /build/web/app ./web/app/ COPY --from=frontend_v2 /build/web/app-v2 ./web/app-v2/ # Login wallpaper cache (Vite does not emit this dir; sync also writes here at runtime) COPY web/app/wallpapers/ ./web/app/wallpapers/ # Install wizard + static SPA assets not emitted by Vite COPY web/app/install.html ./web/app/install.html COPY web/app/servers_import_template.csv ./web/app/servers_import_template.csv RUN mkdir -p ./web/app/vendor COPY web/app/vendor/tailwindcss-browser.js \ web/app/vendor/theme-init.js \ web/app/vendor/theme.css \ web/app/vendor/alpinejs.min.js \ ./web/app/vendor/ COPY docker/entrypoint.sh ./docker/entrypoint.sh RUN chmod +x ./docker/entrypoint.sh \ && test -f /app/web/app/install.html \ && test -f /app/web/app/vendor/alpinejs.min.js \ && test -f /app/web/app/vendor/tailwindcss-browser.js \ && test -f /app/web/app/vendor/theme.css \ && test -f /app/web/app/vendor/theme-init.js ENV PYTHONPATH=/app \ PYTHONUNBUFFERED=1 \ NEXUS_HOST=0.0.0.0 \ NEXUS_PORT=8600 EXPOSE 8600 HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=3 \ CMD curl -sf http://127.0.0.1:8600/health | grep -q '^ok' || exit 1 ENTRYPOINT ["/app/docker/entrypoint.sh"] CMD ["uvicorn", "server.main:app", "--host", "0.0.0.0", "--port", "8600"]