|
| 1 | +# markup-antora — one Antora image to use everywhere. |
| 2 | +# |
| 3 | +# Consolidates the best of the ~9 Antora images that grew across the |
| 4 | +# projects tree. Design priorities, in order: |
| 5 | +# 1. Mermaid rendered FULLY OFFLINE — no Kroki server, no kroki.io, |
| 6 | +# no CDN at build time and none at view time. Diagrams are baked |
| 7 | +# to inline SVG by mermaid-cli (Alpine Chromium + Puppeteer) |
| 8 | +# through the local-mermaid-extension.js Asciidoctor block |
| 9 | +# processor, with content-hash caching so repeated diagrams render |
| 10 | +# once per build. |
| 11 | +# 2. Works under `--user $(id -u):$(id -g)` (rootless) without the |
| 12 | +# Chromium crashpad / cosmiconfig EACCES failures. |
| 13 | +# 3. Offline extras available but not forced: lunr full-text search, |
| 14 | +# a pre-baked Antora UI bundle, and MathJax es5 for LaTeX. |
| 15 | +# 4. asciidoctor-kroki installed-but-unused as an escape hatch. |
1 | 16 | FROM node:20-alpine |
2 | 17 |
|
3 | | -LABEL org.opencontainers.image.title="SKaiNET Antora" \ |
4 | | - org.opencontainers.image.description="Antora site generator with direct local Mermaid rendering (no Kroki round trip)" \ |
| 18 | +LABEL org.opencontainers.image.title="markup-antora" \ |
| 19 | + org.opencontainers.image.description="Universal Antora site generator with offline Mermaid (mermaid-cli), offline search (lunr), pre-baked UI bundle + MathJax. No Kroki, no CDN." \ |
5 | 20 | org.opencontainers.image.source="https://github.com/SKaiNET-developers/SKaiNET" |
6 | 21 |
|
7 | | -# Chromium for mermaid-cli (puppeteer) |
8 | | -RUN apk add --no-cache chromium font-noto |
| 22 | +# Chromium for mermaid-cli (Puppeteer). Full font set so diagram labels, |
| 23 | +# emoji and CJK render correctly (merged from the Daily-StandAPP image). |
| 24 | +RUN apk add --no-cache \ |
| 25 | + chromium \ |
| 26 | + nss \ |
| 27 | + freetype \ |
| 28 | + harfbuzz \ |
| 29 | + ttf-freefont \ |
| 30 | + font-noto \ |
| 31 | + font-noto-emoji \ |
| 32 | + ca-certificates \ |
| 33 | + git |
9 | 34 |
|
10 | | -# HOME=/tmp: chromium's crashpad handler writes its database under $HOME and |
11 | | -# aborts with `chrome_crashpad_handler: --database is required` when the |
12 | | -# container runs as `--user $(id -u):$(id -g)` and $HOME falls back to `/` |
13 | | -# (no passwd entry, not writable). Same motivation as runtime.cache_dir in |
14 | | -# antora-playbook.yml. |
| 35 | +# HOME=/tmp: Chromium's crashpad handler writes its database under $HOME |
| 36 | +# and aborts with `--database is required` when the container runs as a |
| 37 | +# non-root --user and $HOME falls back to `/` (no passwd entry, not |
| 38 | +# writable). Same motivation as runtime.cache_dir in the playbook. |
15 | 39 | ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser \ |
16 | 40 | PUPPETEER_SKIP_DOWNLOAD=true \ |
17 | 41 | HOME=/tmp |
18 | 42 |
|
19 | | -# Install Antora + mermaid-cli into /opt/antora (not /antora which gets |
20 | | -# volume-mounted at run time). asciidoctor-kroki is intentionally NOT |
21 | | -# installed — it depends on a Kroki HTTP server (kroki.io or local) |
22 | | -# which returns 400 for large diagrams when using GET and has no |
23 | | -# offline fallback. We render mermaid directly via mermaid-cli through |
24 | | -# the local-mermaid-extension.js asciidoctor block processor. |
| 43 | +# Install Antora + tooling into /opt/antora (NOT /antora, which is where |
| 44 | +# the project gets volume-mounted at run time). |
| 45 | +# - @mermaid-js/mermaid-cli : offline diagram rendering (the point) |
| 46 | +# - @antora/lunr-extension : offline full-text search |
| 47 | +# - asciidoctor-kroki : escape hatch only; the playbook should |
| 48 | +# use the local mermaid extension instead. |
25 | 49 | WORKDIR /opt/antora |
26 | 50 | RUN npm init -y && npm i --save-exact \ |
27 | 51 | @antora/cli@3.1 \ |
28 | 52 | @antora/site-generator@3.1 \ |
| 53 | + @antora/lunr-extension@1.0.0-alpha.8 \ |
29 | 54 | @mermaid-js/mermaid-cli@11 \ |
| 55 | + asciidoctor-kroki@0.18 \ |
30 | 56 | && npm cache clean --force |
31 | 57 |
|
32 | | -# Make installed modules visible when workdir is the mounted project |
| 58 | +# Make installed modules resolvable even when the workdir is the mounted |
| 59 | +# project (which has no node_modules of its own). |
33 | 60 | ENV NODE_PATH=/opt/antora/node_modules |
34 | 61 |
|
35 | | -# Mermaid-cli config — used by the local-mermaid-extension to drive |
36 | | -# Puppeteer against the pre-installed Alpine Chromium. |
37 | | -RUN echo '{ \ |
38 | | - "executablePath": "/usr/bin/chromium-browser", \ |
39 | | - "args": ["--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage"] \ |
40 | | -}' > /opt/antora/puppeteer-config.json |
41 | | - |
42 | | -# Bake the local mermaid extension in at an absolute path so the |
43 | | -# Antora playbook can reference it without any volume-mount gymnastics. |
| 62 | +# Mermaid-cli / Puppeteer config and the offline block processor, baked |
| 63 | +# in at absolute paths the playbook can reference without mount gymnastics. |
| 64 | +COPY puppeteer-config.json /opt/antora/puppeteer-config.json |
44 | 65 | COPY local-mermaid-extension.js /opt/antora/local-mermaid-extension.js |
45 | 66 |
|
46 | | -# Verify mermaid-cli works end to end at image build time. The cleanup |
47 | | -# also removes mode-0700 root-owned dirs (e.g. /tmp/.config/puppeteer, |
48 | | -# /tmp/.local/share/chromium) that puppeteer/chromium drop into $HOME |
49 | | -# during this run — leaving them in place would make cosmiconfig EACCES |
50 | | -# when the container is later launched with a non-root --user. |
| 67 | +# --- Offline assets (available, not forced) ------------------------------- |
| 68 | + |
| 69 | +# Pre-download the default Antora UI bundle so sites build without hitting |
| 70 | +# gitlab.com. Reference it from a playbook with: |
| 71 | +# ui: |
| 72 | +# bundle: |
| 73 | +# url: /opt/antora-ui/ui-bundle.zip |
| 74 | +# snapshot: true |
| 75 | +RUN mkdir -p /opt/antora-ui \ |
| 76 | + && wget -q -O /opt/antora-ui/ui-bundle.zip \ |
| 77 | + "https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable" |
| 78 | + |
| 79 | +# Pre-download MathJax es5 for offline LaTeX. Copy /opt/mathjax/es5 into a |
| 80 | +# supplemental UI or reference it from your UI template for client-side math. |
| 81 | +RUN mkdir -p /opt/mathjax \ |
| 82 | + && npm pack mathjax@3 --pack-destination /tmp \ |
| 83 | + && tar -xzf /tmp/mathjax-*.tgz -C /tmp \ |
| 84 | + && cp -r /tmp/package/es5 /opt/mathjax/es5 \ |
| 85 | + && rm -rf /tmp/mathjax-* /tmp/package |
| 86 | + |
| 87 | +# --- Build-time smoke test + rootless cleanup ----------------------------- |
| 88 | + |
| 89 | +# Verify mermaid-cli works end to end so a broken image fails the build, |
| 90 | +# not the user's first run. The cleanup also removes the mode-0700 |
| 91 | +# root-owned dirs (/tmp/.config/puppeteer, /tmp/.local/share/chromium, |
| 92 | +# /tmp/.cache, /tmp/.npm) that Puppeteer/Chromium drop into $HOME during |
| 93 | +# this run — leaving them would make cosmiconfig EACCES when the container |
| 94 | +# is later launched with a non-root --user. |
51 | 95 | RUN echo 'graph TD; A-->B;' > /tmp/test.mmd \ |
52 | | - && npx mmdc -i /tmp/test.mmd -o /tmp/test.svg -p /opt/antora/puppeteer-config.json \ |
| 96 | + && /opt/antora/node_modules/.bin/mmdc \ |
| 97 | + -i /tmp/test.mmd -o /tmp/test.svg \ |
| 98 | + -p /opt/antora/puppeteer-config.json --quiet \ |
53 | 99 | && rm -rf /tmp/test.mmd /tmp/test.svg /tmp/.config /tmp/.local /tmp/.npm /tmp/.cache |
54 | 100 |
|
| 101 | +WORKDIR /antora |
55 | 102 | ENTRYPOINT ["/opt/antora/node_modules/.bin/antora"] |
56 | 103 | CMD ["--stacktrace", "antora-playbook.yml"] |
0 commit comments