halkyon/halkyon_learn_curator/Dockerfile
Tizian 「ティツィアーン」 1d2011a676
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-17 19:46:30 +02:00

55 lines
2.8 KiB
Docker

# 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 halkyon_learn_curator/Dockerfile .
#
# A container of its own beside the server (deploy/compose.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 halkyon_learn_curator halkyon_learn_curator
# The workspace root with only the curator package, as the server's Dockerfile does it
# with the server's. The check fails the build loudly if the member list changes shape.
RUN sed -i -e '/^ - halkyon_learn_client$/d' -e '/^ - halkyon_learn_flutter$/d' \
-e '/^ - halkyon_learn_server$/d' pubspec.yaml \
&& grep -q '^ - halkyon_learn_curator$' pubspec.yaml \
&& ! grep -q -e 'halkyon_learn_client' -e 'halkyon_learn_flutter' \
-e 'halkyon_learn_server' pubspec.yaml
RUN dart pub get
WORKDIR /app/halkyon_learn_curator
RUN dart build cli --target bin/curate.dart --output build
# ── Runtime stage ─────────────────────────────────────────────────────────────────
# 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 \
&& 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/halkyon_learn_curator/build/bundle/ ./
COPY --from=build /app/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"]