# LibreLedger — the app plus its persistence server (server.py, standard
# library only). The browser encrypts; the container only stores ciphertext.
#
# Build:  docker build -t libreledger .
# Run:    docker run --rm -p 8080:8080 -v libreledger-data:/data libreledger
# Open:   http://localhost:8080
#
# Base image pinned by version AND index digest (multi-arch). Bump both together.
FROM python:3.14.7-alpine3.24@sha256:c6ead215bfd31f1e433d968853b7a769989117115b728874824e6c0a27cb96fc

ARG VERSION=1.0.0
LABEL org.opencontainers.image.title="LibreLedger" \
      org.opencontainers.image.description="Encrypted personal money ledger: your data is encrypted in your browser; the server never sees it." \
      org.opencontainers.image.version="${VERSION}" \
      org.opencontainers.image.source="https://git.libreportal.org/LibrePortal/LibreLedger" \
      org.opencontainers.image.licenses="AGPL-3.0-only"

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    LIBRELEDGER_HOST=0.0.0.0 \
    LIBRELEDGER_PORT=8080 \
    LIBRELEDGER_DATA_DIR=/data

# Unprivileged by default. LibrePortal may override the uid so the process
# owns its bind mount (under rootless Docker that is container root, which is
# the unprivileged install user on the host).
RUN addgroup -S -g 10001 libreledger \
 && adduser -S -D -H -u 10001 -G libreledger -s /sbin/nologin libreledger \
 && mkdir -p /data \
 && chown libreledger:libreledger /data \
 && chmod 700 /data

WORKDIR /app
COPY --chmod=0444 server.py index.html app.js theme.js crypto-fallback.js styles.css favicon.svg ./
COPY --chmod=0444 banks/*.svg ./banks/
COPY --chmod=0444 vendor/ ./vendor/
RUN find /app -type d -exec chmod 0555 {} +

USER libreledger
EXPOSE 8080
VOLUME ["/data"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD ["python3", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8080/api/health', timeout=4).status == 200 else 1)"]
CMD ["python3", "/app/server.py"]
