| CI builds the image, Modal serves it 5693bd5 nandi 16h ago | 1 | # The web bundle, built once and carried as an image. |
| 2 | # |
| 3 | # Two stages, and the seam between them is the point: the first is a whole |
| 4 | # Flutter SDK and a Nim compiler, about a gigabyte of toolchain that exists |
| 5 | # only to produce `flutter/build/web`; the second is that directory and a |
| 6 | # python to serve it. What gets pushed to the registry, and what Modal pulls |
| 7 | # on every cold start, is the small half. |
| 8 | # |
| 9 | # This is the one place in the tree where a build happens inside a Dockerfile |
| The registry it pushes to is the one it has 627b785 nandi 16h ago | 10 | # rather than in `just` or a Modal sandbox. It is deliberate: rickub is what |
| 11 | # has a registry to push to -- and docker already authenticated to it -- while |
| 12 | # an image is what Modal can deploy without rebuilding anything. The build itself is still `tools/toolchain.sh` -- the |
| CI builds the image, Modal serves it 5693bd5 nandi 16h ago | 13 | # same pinned Flutter and Nim as `just build web` -- so nothing about the |
| 14 | # output depends on being in a container. |
| 15 | |
| 16 | FROM debian:13-slim AS build |
| 17 | |
| 18 | # The toolchain's own needs (git, because Flutter shells out to it against |
| 19 | # its SDK checkout; the unpackers; ca-certificates for curl) and Nim's one |
| 20 | # host dependency, a C compiler. No GTK here and no CMake: the Linux desktop |
| 21 | # target wants those, and this is the web one. |
| 22 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 23 | build-essential ca-certificates curl git tar unzip xz-utils \ |
| 24 | && rm -rf /var/lib/apt/lists/* |
| 25 | |
| 26 | WORKDIR /src |
| 27 | COPY . . |
| 28 | |
| 29 | # The same two steps as `just build web`, inlined because `just` is not here |
| 30 | # and is not worth an install for one call. The core is compiled to |
| 31 | # JavaScript and copied into `flutter/web/` rather than into the output, |
| 32 | # because `flutter build web` copies that directory into the bundle -- which |
| 33 | # is what makes the page's `<script src="frq_core.js">` resolve the same |
| 34 | # either way. |
| 35 | RUN tools/toolchain.sh exec -- bash -euo pipefail -c '\ |
| 36 | mkdir -p /src/build/web && cd /src/nim && \ |
| 37 | nim js -d:release --hints:off --path:src --path:web \ |
| 38 | --out:/src/build/web/frq_core.js web/frq_web.nim && \ |
| 39 | cp /src/build/web/frq_core.js /src/flutter/web/frq_core.js && \ |
| 40 | cd /src/flutter && flutter pub get && flutter build web' |
| 41 | |
| 42 | # python:*-slim and not debian:*-slim, for two reasons that happen to agree: |
| 43 | # Modal runs its own client inside the container, so the image needs a Python |
| 44 | # it can use, and the server is `http.server` -- the same one `just run web` |
| 45 | # starts on localhost, so what is served here is served the same way there. |
| 46 | FROM python:3.13-slim |
| 47 | |
| 48 | COPY --from=build /src/flutter/build/web /srv/web |
| 49 | |
| 50 | EXPOSE 8000 |
| 51 | CMD ["python3", "-m", "http.server", "8000", "--directory", "/srv/web"] |