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