halkyon/apps/learn/halkyon_learn_curator/Dockerfile

52 lines
2.6 KiB
Text
Raw Normal View History

# The dictionaries' image: the curator, keeping a server's dictionary files current
# from EDRDG's files of the day (`curate update`, the README). Built from the
# repository root (the build context), where the workspace's root pubspec and lockfile
# live:
#
# docker build -f apps/learn/halkyon_learn_curator/Dockerfile .
#
# A container of its own beside the server (deploy/compose.learn.yaml, decided 2026-10-09):
# the curator (AGPL) never enters the server's image or process, and a conversion
# that fails can't touch the server. They share only the folder of files.
# ── Build stage: compile the curator to a native executable ───────────────────────
FROM dart:3.13.4 AS build
WORKDIR /app
COPY pubspec.yaml pubspec.lock ./
COPY tool/workspace_only.sh tool/
COPY apps/learn/halkyon_learn_curator apps/learn/halkyon_learn_curator
# The workspace root with only the curator package, as the server's Dockerfile does it
# with the server's.
RUN sh tool/workspace_only.sh apps/learn/halkyon_learn_curator
RUN dart pub get
WORKDIR /app/apps/learn/halkyon_learn_curator
RUN dart build cli --target bin/curate.dart --output build
# ── Runtime stage ─────────────────────────────────────────────────────────────────
feat(dictionary): Japanese cut into words and looked up on the device Once the person agrees, the device holds MeCab's IPADIC and the instance's JMdict and cuts lines as Jisho.org does, so their text never leaves it (ADR 0012). MeCab comes through mecab_for_dart, whose build hook compiles it; its tokens are grouped by Ve's rules, written anew in Dart, with に kept a word of its own. Each word is found as it stands or as a form of a word, else by its dictionary form, else as the longest words it holds from token to token; longer words over token boundaries are offered as before. The curator packs Ubuntu's compiled IPADIC beside the dictionary files (curate ipadic, and every update run). The server exports its JMdict from its tables, so the device finds the same keys and keeps the same versions, and serves both at /device-dictionaries/, named in dictionary.deviceFiles('ja') with their hashes; Caddy forwards the path. The app checks each file against its hash, unpacks IPADIC, builds a SQLite database from the export on an isolate, and asks the instance for newer files every 30 days, downloading only what changed. The Watch screen offers the download once per device with its size (34 MB, some 150 MB once set up); Settings downloads and removes them. Without them, or should cutting on the device fail, lines go to the instance as before. MeCab's, IPADIC's and Ve's licences join the licence list. Every build now needs a C++ compiler; mecab_for_dart holds code_assets at 1.x. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-15 21:55:00 +02:00
# Ubuntu 24.04 as the server's, with CA certificates for EDRDG's HTTPS, and MeCab's
# IPADIC, which the package compiles as it is installed: the curator packs it for the
# app's devices (ADR 0012). Its sources go once it is compiled.
FROM ubuntu:24.04
RUN apt-get update \
feat(dictionary): Japanese cut into words and looked up on the device Once the person agrees, the device holds MeCab's IPADIC and the instance's JMdict and cuts lines as Jisho.org does, so their text never leaves it (ADR 0012). MeCab comes through mecab_for_dart, whose build hook compiles it; its tokens are grouped by Ve's rules, written anew in Dart, with に kept a word of its own. Each word is found as it stands or as a form of a word, else by its dictionary form, else as the longest words it holds from token to token; longer words over token boundaries are offered as before. The curator packs Ubuntu's compiled IPADIC beside the dictionary files (curate ipadic, and every update run). The server exports its JMdict from its tables, so the device finds the same keys and keeps the same versions, and serves both at /device-dictionaries/, named in dictionary.deviceFiles('ja') with their hashes; Caddy forwards the path. The app checks each file against its hash, unpacks IPADIC, builds a SQLite database from the export on an isolate, and asks the instance for newer files every 30 days, downloading only what changed. The Watch screen offers the download once per device with its size (34 MB, some 150 MB once set up); Settings downloads and removes them. Without them, or should cutting on the device fail, lines go to the instance as before. MeCab's, IPADIC's and Ve's licences join the licence list. Every build now needs a C++ compiler; mecab_for_dart holds code_assets at 1.x. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-15 21:55:00 +02:00
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates mecab-ipadic-utf8 \
&& test -s /var/lib/mecab/dic/ipadic-utf8/sys.dic \
&& rm -rf /usr/share/mecab/dic/ipadic /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /app/apps/learn/halkyon_learn_curator/build/bundle/ ./
COPY --from=build /app/apps/learn/halkyon_learn_curator/data/ data/
# An unprivileged user of its own: user ID 10001, shared with neither the containers
# of PostgreSQL and the server (999) nor the CI runner on the host (61000). The folder
# it writes into belongs to it, which a new volume mounted there takes over.
RUN useradd --system --uid 10001 --no-create-home --shell /usr/sbin/nologin curator \
&& mkdir /dictionaries \
&& chown curator /dictionaries
USER curator
# Updates the files whenever they are a week old (EDRDG's licence asks at least
# monthly), and sleeps in between.
ENTRYPOINT ["./bin/curate", "update", "--into", "/dictionaries", "--data", "data"]
CMD ["--every", "7"]