# syntax=docker/dockerfile:1.7
#
# Multi-stage build for the ai-memory MCP server.
# Builder: rust:1.95-slim with the release binary cached against
#          BuildKit's cargo registry + target caches.
# Runtime: debian:bookworm-slim with a non-root `ai-memory` user that
#          owns /data. CA certificates included for outgoing HTTPS (LLM
#          providers in M6+).
#
# The default final target builds the binary from source. Release automation and
# CI can target the prebuilt runtime stages after downloading native release
# artifacts, avoiding duplicate Rust compiles in Docker jobs.

FROM rust:1.95-slim-bookworm AS builder
WORKDIR /work
RUN apt-get update \
 && apt-get install -y --no-install-recommends pkg-config build-essential curl ca-certificates \
 && rm -rf /var/lib/apt/lists/*
COPY Cargo.toml Cargo.lock rust-toolchain.toml deny.toml ./
COPY crates ./crates
# `evals/` is a workspace member (off-tree A/B harness, not shipped
# in the image — but Cargo refuses to parse the workspace manifest
# if a declared member doesn't exist on disk). Copy the dir so the
# manifest resolves; `-p ai-memory-cli` keeps the binary build narrow.
COPY evals ./evals
# `docs/logo*.png` are include_bytes!'d by ai-memory-web's static
# routes at compile time, so they must be in the build context.
COPY docs ./docs
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    --mount=type=cache,target=/work/target \
    cargo build --locked --release -p ai-memory-cli \
 && cp target/release/ai-memory /usr/local/bin/ai-memory

FROM debian:bookworm-slim AS runtime-base
RUN apt-get update \
 && apt-get install -y --no-install-recommends ca-certificates \
 && rm -rf /var/lib/apt/lists/* \
 && useradd --system --uid 1000 --user-group --home-dir /data \
         --shell /usr/sbin/nologin ai-memory \
 && mkdir -p /data \
 && chown -R ai-memory:ai-memory /data
# Lifecycle-hook scripts bundled into the image so docker-only users
# can `ai-memory setup-agent` without needing a repo checkout. The
# scripts live on a path scanned by `install_hooks::resolve_hooks_dir`
# (and by `setup_agent::resolve_source`).
COPY hooks /usr/local/share/ai-memory/hooks
ENV AI_MEMORY_DATA_DIR=/data
# Allow Docker Desktop's host alias by default so the macOS wrapper's
# thin-client commands — which reach the loopback-published server from a
# one-shot helper container via host.docker.internal — aren't rejected by the
# Host-header DNS-rebinding guard (issue #107). This widens only the *image*
# default; native (non-Docker) installs keep the loopback-only default, and
# exposed/homelab deployments still set their own `AI_MEMORY_ALLOWED_HOSTS`,
# which replaces this value entirely.
ENV AI_MEMORY_ALLOWED_HOSTS="localhost,127.0.0.1,::1,host.docker.internal"
# Tell the server it is containerised, so the unauthenticated-bind guard in
# `serve` knows the `0.0.0.0` bind below is a namespace requirement rather
# than evidence of network exposure (issue #407). `/.dockerenv` covers Docker
# and `/run/.containerenv` covers Podman; this makes the signal explicit and
# runtime-independent.
ENV AI_MEMORY_IN_CONTAINER=1
WORKDIR /data
EXPOSE 49374
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
    CMD ["/usr/local/bin/ai-memory", "status"]
ENTRYPOINT ["/usr/local/bin/ai-memory"]
CMD ["serve", "--transport", "http", "--bind", "0.0.0.0:49374", "--enable-web"]

FROM runtime-base AS runtime-prebuilt-amd64
COPY --chmod=0755 dist/docker/ai-memory-linux-x86_64/ai-memory /usr/local/bin/ai-memory
USER ai-memory

FROM runtime-base AS runtime-prebuilt-arm64
COPY --chmod=0755 dist/docker/ai-memory-linux-aarch64/ai-memory /usr/local/bin/ai-memory
USER ai-memory

FROM runtime-base AS runtime-source
COPY --from=builder /usr/local/bin/ai-memory /usr/local/bin/ai-memory
USER ai-memory
