# Dockerfile.local - Uses local module sources via go workspace # For pre-release CI builds where module versions aren't published yet # --- UI Build Stage: Build the React + Vite frontend --- FROM node:25-alpine3.23@sha256:cf38e1f3c28ac9d81cdc0c51d8220320b3b618780e44ef96a39f76f7dbfef023 AS ui-builder WORKDIR /app ENV CI=1 ENV NODE_OPTIONS=--max-old-space-size=4096 # Copy UI package files and install dependencies COPY ui/package*.json ./ RUN npm ci # Copy UI source code COPY ui/ ./ # Build UI (skip the copy-build step) RUN npm run build-enterprise -- --debug # Skip the copy-build step since we'll copy the files in the Go build stage # --- Go Build Stage: Compile the Go binary using local modules --- FROM golang:1.26.2-alpine3.23@sha256:f85330846cde1e57ca9ec309382da3b8e6ae3ab943d2739500e08c86393a21b1 AS builder WORKDIR /build # Install dependencies including gcc for CGO and sqlite RUN apk add --no-cache gcc musl-dev sqlite-dev binutils binutils-gold # Set environment for CGO-enabled build (required for go-sqlite3) ENV CGO_ENABLED=1 GOOS=linux # Copy all local modules COPY core/ ./core/ COPY framework/ ./framework/ COPY plugins/ ./plugins/ COPY transports/ ./transports/ # Set up go workspace to resolve local module dependencies RUN go work init && \ go work use ./core && \ go work use ./framework && \ go work use ./plugins/compat && \ go work use ./plugins/governance && \ go work use ./plugins/jsonparser && \ go work use ./plugins/logging && \ go work use ./plugins/maxim && \ go work use ./plugins/mocker && \ go work use ./plugins/otel && \ go work use ./plugins/prompts && \ go work use ./plugins/semanticcache && \ go work use ./plugins/telemetry && \ go work use ./transports # Download external (non-local) dependencies RUN cd /build/transports && go mod download # Copy UI build output into transports COPY --from=ui-builder /app/out ./transports/bifrost-http/ui # Build the binary with CGO enabled and static SQLite linking ARG VERSION=unknown RUN cd /build/transports && \ go build \ -ldflags="-w -s -X main.Version=v${VERSION} -extldflags '-static'" \ -a -trimpath \ -tags "sqlite_static" \ -o /app/main \ ./bifrost-http # Verify build succeeded RUN test -f /app/main || (echo "Build failed" && exit 1) # --- Runtime Stage: Minimal runtime image --- FROM alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 WORKDIR /app # Install runtime dependencies for CGO-enabled binary # musl: C standard library (required for CGO binaries) # libgcc: GCC runtime library # ca-certificates: For HTTPS connections RUN apk add --no-cache musl libgcc ca-certificates wget zlib=1.3.2-r0 # Create data directory and set up user COPY --from=builder /app/main . COPY --from=builder /build/transports/docker-entrypoint.sh . # Getting arguments ARG ARG_APP_PORT=8080 ARG ARG_APP_HOST=0.0.0.0 ARG ARG_LOG_LEVEL=info ARG ARG_LOG_STYLE=json ARG ARG_APP_DIR=/app/data # Environment variables with defaults (can be overridden at runtime) ENV APP_PORT=$ARG_APP_PORT \ APP_HOST=$ARG_APP_HOST \ LOG_LEVEL=$ARG_LOG_LEVEL \ LOG_STYLE=$ARG_LOG_STYLE \ APP_DIR=$ARG_APP_DIR RUN mkdir -p $APP_DIR/logs && \ adduser -D -s /bin/sh appuser && \ chown -R appuser:appuser /app && \ chmod +x /app/docker-entrypoint.sh USER appuser # Declare volume for data persistence VOLUME ["/app/data"] EXPOSE $APP_PORT # Health check for container status monitoring HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 -O /dev/null http://127.0.0.1:${APP_PORT}/health || exit 1 # Use entrypoint script that handles volume permissions and argument processing ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["/app/main"]