webfind 0.5.0

Self-hosted native search engine for AI agents — pure CLI, zero cost
# syntax=docker/dockerfile:1

# -----------------------------------------------------------------------------
# Stage 1: Planner — generate a locked dependency recipe for cargo-chef.
# -----------------------------------------------------------------------------
FROM rust:1.97 AS planner
WORKDIR /app

RUN cargo install cargo-chef --locked

COPY Cargo.toml Cargo.lock ./
RUN cargo chef prepare --recipe-path recipe.json

# -----------------------------------------------------------------------------
# Stage 2: Builder — cache dependency builds, then compile the application.
# -----------------------------------------------------------------------------
FROM rust:1.97 AS builder
WORKDIR /app

RUN cargo install cargo-chef --locked

# Install Node.js for building Tailwind CSS assets.
# Combine into one RUN to ensure PATH and binaries are properly set up.
RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates curl gnupg \
    && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
    && apt-get install -y --no-install-recommends nodejs \
    && rm -rf /var/lib/apt/lists/* \
    && node --version \
    && npm --version

# Reduce release-build memory usage inside Docker so large crates don't OOM.
# These overrides are intentionally conservative; they trade peak memory for longer compile times.
ENV CARGO_PROFILE_RELEASE_LTO=false
ENV CARGO_PROFILE_RELEASE_CODEGEN_UNITS=64

# Allow overriding parallel job count via --build-arg BUILD_JOBS=N.
# Use "default" to let Cargo pick the core count; set lower (e.g. 1 or 2) on memory-constrained hosts.
ARG BUILD_JOBS=default
ENV CARGO_BUILD_JOBS=${BUILD_JOBS}

# Cache dependency compilation. This layer is invalidated only when Cargo.toml/Cargo.lock change.
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

# Build frontend assets first so css is ready before Rust compilation finishes.
# Touch a marker file to force Docker cache invalidation on each build.
COPY assets ./assets
# Copy templates early so Tailwind's @source can scan them during build.
COPY templates ./templates
RUN cd assets \
    && npm ci --no-audit --no-fund --ignore-scripts \
    && npm run build:css \
    && npm run copy:js \
    && ls -la js/ output.css

# Copy source and build the application binary. This layer is invalidated when src/ changes.
COPY src ./src
COPY schema ./schema
RUN cargo build --release --bin webfind

# -----------------------------------------------------------------------------
# Stage 3: Runtime — minimal image with just the compiled binary.
# -----------------------------------------------------------------------------
FROM ubuntu:24.04 AS runtime

RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY --from=builder /app/target/release/webfind /usr/local/bin/webfind
COPY --from=builder /app/assets ./assets
COPY --from=builder /app/templates ./templates

ENV WEBFIND_DATA_DIR=/data
VOLUME ["/data"]
# Container-internal ports:
#   4747 : API/MCP over HTTP (Streamable HTTP)
#   4749 : HTML GUI (Google-style search)
# When running via docker compose, the host ports are:
#   5748 -> 4747 (API)
#   5750 -> 4749 (GUI)
EXPOSE 4747 4749

ENTRYPOINT ["webfind"]
CMD ["serve", "--transport", "http", "--gui-port", "4749"]