# syntax=docker/dockerfile:1 FROM alpine:3.24 AS build # VERSION is declared after the expensive layers: the legacy builder # invalidates every layer that follows a changed build argument. # Alpine's ncurses has no ncursesw/ include directory; the TUI includes # like Debian, so point it at the one header. RUN apk add --no-cache build-base openssl-dev ncurses-dev \ && mkdir -p /usr/include/ncursesw \ && ln -s ../ncurses.h /usr/include/ncursesw/ncurses.h WORKDIR /src COPY . . ARG VERSION=0.1.0-dev # With .prebuilt/ the static aarch64 binaries are cross-compiled on the # development machine (deploy/Dockerfile.cross); otherwise build and test from # source on this host. RUN if [ -x .prebuilt/bokfd ]; then \ mkdir -p build && \ cp .prebuilt/bokfd .prebuilt/bokfctl .prebuilt/bokftui \ .prebuilt/bokfweb build/; \ else \ make -j"$(nproc)" backend build/bokftui build/bokfweb \ VERSION="$VERSION" \ && make test-core VERSION="$VERSION"; \ fi \ && strip build/bokfd build/bokfctl build/bokftui build/bokfweb \ && mkdir -p build/locale \ && if [ -d .prebuilt/locale ]; then cp -a .prebuilt/locale/. build/locale/; fi # The web frontend (image bokf-web, `--target web`): Caddy for routing, the # bokfweb login gate, ttyd and bokftui in web mode. It reaches bokfd only # through the protocol socket; no database, no secrets, no certificates # (TLS is the host's reverse proxy). Everything runs as an unprivileged # user; Caddy listens on 8790. FROM alpine:3.24 AS web RUN apk add --no-cache ca-certificates caddy ttyd ncurses-terminfo-base \ ncurses-libs libssl3 libcrypto3 \ && addgroup -S bokfd \ && adduser -S -D -H -u 10001 -G bokfd -s /sbin/nologin bokfd COPY --from=build /src/build/bokftui /src/build/bokfweb /usr/local/bin/ # glibc locale data for the cross-built static binaries (empty for a native # musl build, which needs none); the check fails the build without UTF-8 COPY --from=build /src/build/locale/ /usr/lib/locale/ COPY deploy/bokftui-web deploy/web-entrypoint.sh /usr/local/bin/ COPY deploy/Caddyfile /etc/caddy/Caddyfile RUN chmod 0755 /usr/local/bin/bokftui-web /usr/local/bin/web-entrypoint.sh \ && LANG=C.UTF-8 bokfweb --check-locale ENV BOKFD_SOCKET=/run/bokfd/bokfd.sock \ TERM=xterm-256color \ LANG=C.UTF-8 USER 10001 EXPOSE 8790 HEALTHCHECK --interval=15s --timeout=3s --start-period=5s --retries=3 \ CMD ["wget", "-q", "-O", "/dev/null", "http://127.0.0.1:7682/healthz"] ENTRYPOINT ["/usr/local/bin/web-entrypoint.sh"] # The runtime image carries the daemon and bokfctl only, statically linked # against OpenSSL and the C library; the ncurses TUI is a frontend (on the # machine you sit at, or in the web image above). It is the last stage, so a # plain `docker build` still produces it. FROM alpine:3.24 AS runtime RUN apk add --no-cache ca-certificates util-linux \ && addgroup -S bokfd \ && adduser -S -D -H -u 10001 -G bokfd -s /sbin/nologin bokfd \ && install -d -o bokfd -g bokfd /var/lib/bokfd /var/lib/bokfd/backup \ /var/lib/bokfd/export /var/lib/bokfd/certs /run/bokfd COPY --from=build /src/build/bokfd /src/build/bokfctl /usr/local/bin/ COPY --from=build /src/data/bas_k2.csv /src/data/bas_k3.csv \ /usr/local/share/bokf/ COPY deploy/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod 0755 /usr/local/bin/docker-entrypoint.sh ENV BOKFD_DB=/var/lib/bokfd/bokfd.db \ BOKFD_SOCKET=/run/bokfd/bokfd.sock \ BOKFD_BACKUP_DIR=/var/lib/bokfd/backup \ BOKFD_EXPORT_DIR=/var/lib/bokfd/export VOLUME ["/var/lib/bokfd", "/run/bokfd"] HEALTHCHECK --interval=10s --timeout=3s --start-period=3s --retries=3 \ CMD ["bokfctl", "health"] ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] CMD ["bokfd"]