# syntax=docker/dockerfile:1.7 FROM node:20-bookworm-slim AS frontend-builder WORKDIR /build/frontend ENV CI=1 NEXT_TELEMETRY_DISABLED=1 ARG NPM_REGISTRY="https://registry.npmmirror.com" ARG NPM_FETCH_RETRIES="5" ARG NPM_FETCH_RETRY_MIN_TIMEOUT="20000" ARG NPM_FETCH_RETRY_MAX_TIMEOUT="120000" COPY frontend/package.json frontend/package-lock.json* ./ RUN --mount=type=cache,target=/root/.npm \ npm config set registry "${NPM_REGISTRY}" && \ npm config set fetch-retries "${NPM_FETCH_RETRIES}" && \ npm config set fetch-retry-mintimeout "${NPM_FETCH_RETRY_MIN_TIMEOUT}" && \ npm config set fetch-retry-maxtimeout "${NPM_FETCH_RETRY_MAX_TIMEOUT}" && \ npm ci COPY frontend/ ./ ARG NEXT_PUBLIC_AUTH_PORTAL_URL="" ARG NEXT_PUBLIC_AUTH_PORTAL_PORT="3081" ENV NEXT_PUBLIC_AUTH_PORTAL_URL=${NEXT_PUBLIC_AUTH_PORTAL_URL} ENV NEXT_PUBLIC_AUTH_PORTAL_PORT=${NEXT_PUBLIC_AUTH_PORTAL_PORT} # API / WS 走同域反代,不在构建时写死实例地址。 RUN npm run build FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS runtime ENV DEBIAN_FRONTEND=noninteractive \ APP_PUBLIC_PORT=8080 \ APP_FRONTEND_PORT=3000 \ APP_BACKEND_PORT=18080 \ BEAVER_HOME=/root/.beaver \ BEAVER_CONFIG_PATH=/root/.beaver/config.json \ BEAVER_WORKSPACE=/root/.beaver/workspace \ BEAVER_AUTH_FILE=/root/.beaver/web_auth_users.json \ PORT=3000 \ HOSTNAME=127.0.0.1 ARG NPM_REGISTRY="https://registry.npmmirror.com" ARG NPM_FETCH_RETRIES="5" ARG NPM_FETCH_RETRY_MIN_TIMEOUT="20000" ARG NPM_FETCH_RETRY_MAX_TIMEOUT="120000" ARG APT_MIRROR="https://mirrors.tuna.tsinghua.edu.cn/debian" ARG PYPI_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple" RUN find /etc/apt -type f \( -name "*.list" -o -name "*.sources" \) -exec \ sed -i "s|http://deb.debian.org/debian-security|${APT_MIRROR}-security|g; s|http://deb.debian.org/debian|${APT_MIRROR}|g; s|http://security.debian.org/debian-security|${APT_MIRROR}-security|g" {} + && \ apt-get update && \ apt-get install -y --no-install-recommends curl ca-certificates gnupg git nginx dumb-init && \ mkdir -p /etc/apt/keyrings && \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \ apt-get update && \ apt-get install -y --no-install-recommends nodejs && \ apt-get purge -y gnupg && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/app/backend COPY backend/pyproject.toml backend/README.md ./ COPY backend/beaver/ ./beaver/ RUN uv pip install --system --no-cache --index-url "${PYPI_INDEX_URL}" ".[channels]" WORKDIR /opt/app/frontend COPY --from=frontend-builder /build/frontend/next.config.js ./ COPY --from=frontend-builder /build/frontend/public ./public COPY --from=frontend-builder /build/frontend/package.json ./package.json COPY --from=frontend-builder /build/frontend/.next/standalone ./ COPY --from=frontend-builder /build/frontend/.next/static ./.next/static WORKDIR /opt/app COPY nginx.conf /opt/app/nginx.conf COPY entrypoint.sh /opt/app/entrypoint.sh RUN chmod +x /opt/app/entrypoint.sh && \ mkdir -p /var/lib/nginx/body /root/.beaver/workspace EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=5 \ CMD curl -fsS "http://127.0.0.1:${APP_PUBLIC_PORT}/api/ping" >/dev/null || exit 1 ENTRYPOINT ["dumb-init", "--", "/opt/app/entrypoint.sh"]