# syntax=docker/dockerfile:1.4 # aldabra — Cardano lite wallet over MCP. # # Multi-stage: # 1. builder — rust toolchain, cargo build --release # 2. runtime — debian:bookworm-slim, just the binary + ca-certs. # # Produces an `aldabra/mcp` image with the MCP-server binary baked in. # Pulled anywhere the MCP server is needed — usually as a sidecar # spawned by an MCP client (Claude Code, etc). # # Required env at runtime: # ALDABRA_DATA directory containing mnemonic.age (must # already exist; bootstrap separately on # first install) # ALDABRA_NETWORK mainnet | preview | preprod (default preprod) # ALDABRA_KOIOS_BASE defaults to public Koios for the network # ALDABRA_PASSPHRASE unlocks mnemonic.age. Source from a docker # secret or systemd EnvironmentFile — never # commit it. FROM rust:1.95-bookworm AS builder WORKDIR /build # Cache deps separately from source. Copy manifests + dummy bins so # `cargo build` resolves and downloads everything before the real # source rebuilds invalidate the layer. COPY Cargo.toml ./ COPY crates/aldabra-core/Cargo.toml crates/aldabra-core/ COPY crates/aldabra-chain/Cargo.toml crates/aldabra-chain/ COPY crates/aldabra-mcp/Cargo.toml crates/aldabra-mcp/ RUN mkdir -p crates/aldabra-core/src crates/aldabra-chain/src crates/aldabra-mcp/src && \ echo 'fn main() {}' > crates/aldabra-mcp/src/main.rs && \ echo '' > crates/aldabra-core/src/lib.rs && \ echo '' > crates/aldabra-chain/src/lib.rs && \ cargo build --release --bin aldabra || true && \ rm -rf crates/*/src COPY crates ./crates # Touch every src file so cargo notices and rebuilds. The dummy-source # trick above leaves stale build artifacts otherwise. RUN find crates -name '*.rs' -exec touch {} + RUN cargo build --release --bin aldabra && \ strip target/release/aldabra FROM debian:bookworm-slim AS runtime # rustls-tls needs ca-certificates to verify Koios's TLS cert. # tini for proper signal forwarding when running as PID 1. RUN apt-get update && \ apt-get install -y --no-install-recommends ca-certificates tini && \ rm -rf /var/lib/apt/lists/* COPY --from=builder /build/target/release/aldabra /usr/local/bin/aldabra # Escrow V3 validator CBOR. Baked at /etc/aldabra/escrow/validator.cbor.hex # so MCP escrow_*_unsigned tools can pass it via `validator_script_path`. # An MCP arg-truncation bug at >4500 hex chars makes the inline # `validator_script_cbor_hex` option unusable for the 7902-char compiled # validator, so file-path mode is the canonical way to wire it. Validator # hash: a8081acef26935d9b5f44b92052178e17301b6d6e6808c91c5b56f5d — check # against the file's compiled hash before invoking on-chain ops. COPY aiken-escrow/validator.cbor.hex /etc/aldabra/escrow/validator.cbor.hex COPY aiken-escrow/plutus.json /etc/aldabra/escrow/plutus.json # Default data dir — mount a volume here in compose / k8s / docker run. ENV ALDABRA_DATA=/var/lib/aldabra RUN mkdir -p /var/lib/aldabra && chmod 700 /var/lib/aldabra # Non-root user for runtime. Mnemonic.age is owner-readable only # (chmod 600 from the bootstrap path), so the runtime UID must own # the data dir. RUN groupadd -r aldabra && useradd -r -g aldabra -d /var/lib/aldabra aldabra && \ chown -R aldabra:aldabra /var/lib/aldabra USER aldabra # tini handles SIGTERM and reaps zombies. ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/aldabra"]