Dockerfile
Rama main · réplica de lectura del repositorio original.
# ── Build stage ──────────────────────────────────────────────────────
FROM --platform=$BUILDPLATFORM rust:1.95.0-bookworm AS builder
# Install cross-compilation toolchains when cross-compiling.
# xmp_toolkit vendors Adobe's C++ XMP Toolkit and compiles it via `cc` on
# every build, so the arm64 branch needs g++-aarch64-linux-gnu in addition
# to the C compiler.
ARG TARGETPLATFORM
RUN case "$TARGETPLATFORM" in \
"linux/amd64") \
apt-get update && \
apt-get install -y libdbus-1-dev ;; \
"linux/arm64") \
dpkg --add-architecture arm64 && \
apt-get update && \
apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libdbus-1-dev:arm64 ;; \
esac
WORKDIR /build
# Resolve target triple and linker from TARGETPLATFORM once.
# Shared by the dependency-cache and real build steps.
RUN case "$TARGETPLATFORM" in \
"linux/amd64") echo "x86_64-unknown-linux-gnu" > /tmp/target ;; \
"linux/arm64") echo "aarch64-unknown-linux-gnu" > /tmp/target ;; \
esac && \
rustup target add $(cat /tmp/target)
# Cache dependency compilation: copy manifests first, build a dummy, then
# copy the real source. This means changing src/ doesn't invalidate the
# dependency layer.
COPY Cargo.toml Cargo.lock build.rs ./
RUN export TARGET=$(cat /tmp/target) && \
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc && \
export CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ && \
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_CXX=aarch64-linux-gnu-g++ && \
export PKG_CONFIG_ALLOW_CROSS=1 && \
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig && \
mkdir src && echo 'fn main() {}' > src/main.rs && \
cargo build --release --target $TARGET && \
rm -rf src target/$TARGET/release/deps/kei*
COPY src/ src/
RUN export TARGET=$(cat /tmp/target) && \
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc && \
export CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ && \
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_CXX=aarch64-linux-gnu-g++ && \
export PKG_CONFIG_ALLOW_CROSS=1 && \
export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig && \
cargo build --release --target $TARGET && \
cp target/$TARGET/release/kei /kei
# ── Runtime stage ────────────────────────────────────────────────────
FROM debian:bookworm-20261005-slim
RUN apt-get update && \
apt-get install -y --no-install-recommends bash curl ca-certificates libdbus-1-3 gosu && \
rm -rf /var/lib/apt/lists/*
COPY --from=builder /kei /usr/local/bin/kei
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
VOLUME ["/config", "/photos"]
# Always-on HTTP server: /healthz (health check) and /metrics (Prometheus).
# Default port 9090. For a custom [server].port, set KEI_HEALTHCHECK_PORT
# to the same port (including when using a custom config path).
EXPOSE 9090
HEALTHCHECK --interval=60s --timeout=5s --start-period=15m --retries=3 \
CMD curl -fsS "http://localhost:${KEI_HEALTHCHECK_PORT:-9090}/healthz" || exit 1
# entrypoint.sh drops to PUID:PGID when those env vars are set; otherwise
# exec's kei as root (preserves prior behavior). Required for NAS
# deployments where files must be host-user-owned (Synology Photos,
# Unraid, TrueNAS Scale).
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
# Container runtime glue: keep sessions, state DB, and credentials on the
# mounted /config volume. Persistent user settings live in /config/config.toml.
ENV KEI_DATA_DIR=/config
# Keep glibc from reserving one large malloc arena per worker thread. This
# lowers virtual memory size for long-running watch containers without changing
# kei's actual resident memory target.
ENV MALLOC_ARENA_MAX=2
CMD ["service", "run", "--config", "/config/config.toml"]