# The server image. Built from the repository root (the build context), because the # workspace's root pubspec and lockfile live there: # # docker build -f apps/learn/halkyon_learn_server/Dockerfile . # # Based on Serverpod's template, with three changes: Dart 3.13 (our SDK floor), an # Ubuntu 24.04 runtime instead of alpine + Dart's minimal glibc runtime (same # distribution as our servers; complete glibc, which Serverpod 4's bundled SQLite # libraries need), and a start command that passes Docker's stop signal on. # ── Build stage: compile the server 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_server apps/learn/halkyon_learn_server COPY packages/halkyon_base_server packages/halkyon_base_server COPY packages/halkyon_base_client packages/halkyon_base_client COPY packages/halkyon_oidc_server packages/halkyon_oidc_server COPY packages/halkyon_oidc_client packages/halkyon_oidc_client # The workspace root with only the server and the modules it builds on (halkyon_base, # and the OpenID Connect module halkyon_base signs in with, ADR 0023): neither the # other apps nor Learn's client package are needed to build the server, and the Flutter # packages would need Flutter. The base module's client comes along only because the # module's tests depend on it (SRP's two halves, held to each other), and pub resolves # every member's dev dependencies, the OpenID Connect module's client because that # client depends on it; the server never imports either. Everything else stays as the # repository has it, above all the dependency overrides, which bring the server our # fork of the offline sync package (fetched with the git the Dart image has). RUN sh tool/workspace_only.sh apps/learn/halkyon_learn_server packages/halkyon_base_server packages/halkyon_base_client packages/halkyon_oidc_server packages/halkyon_oidc_client RUN dart pub get WORKDIR /app/apps/learn/halkyon_learn_server RUN dart build cli --target bin/main.dart --output build RUN mv build/bundle/bin/main build/bundle/bin/server RUN mkdir -p config migrations # ── Runtime stage ───────────────────────────────────────────────────────────────── # Ubuntu 24.04: glibc 2.39 (the bundled binaries need at most 2.34, measured) and # libgcc_s (needed by libsqlite3_connection_pool, a Rust library; a server running # against Postgres never loads it, but a future code path might). CA certificates # for outgoing TLS, e.g. GitHub sign-in. git for the published studysets' releases # (ADR 0005, rule 3), which the server writes through the git command. FROM ubuntu:24.04 RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates git \ && rm -rf /var/lib/apt/lists/* WORKDIR /app ENV runmode=production ENV serverid=default ENV logging=normal ENV role=monolith COPY --from=build /app/apps/learn/halkyon_learn_server/build/bundle/ ./ COPY --from=build /app/apps/learn/halkyon_learn_server/config/ config/ COPY --from=build /app/apps/learn/halkyon_learn_server/migrations/ migrations/ # Mozilla's Public Suffix List, for the Jellyfin server the instance suggests. COPY --from=build /app/apps/learn/halkyon_learn_server/data/ data/ COPY --from=build /app/apps/learn/halkyon_learn_server/lib/src/generated/protocol.yaml lib/src/generated/protocol.yaml # The server needs no root rights (it listens on 8080 and writes only into the # repositories folder), so it runs as an unprivileged system user. The folder is the # app user's, and a new volume mounted on it takes that over. RUN useradd --system --no-create-home --shell /usr/sbin/nologin app \ && mkdir repositories && chown app:app repositories USER app # Only the API server runs in production (no Insights, no web server). EXPOSE 8080 # `exec` makes the server PID 1, so it receives Docker's SIGTERM and shuts down # cleanly; extra arguments (e.g. --apply-migrations) come from the container command. ENTRYPOINT ["/bin/sh", "-c", "exec ./bin/server --mode=$runmode --server-id=$serverid --logging=$logging --role=$role \"$@\"", "--"] CMD []