The mesh refused to place it — two of its three containers named mesh-runtime-lavinmq@sha256:000…0, "a placeholder digest, which is never a real image". That refusal was right, and the belief behind the placeholder was that lavinmq needs no building because its broker is an upstream image. The broker is upstream. The module is not the broker. It carries a run-once bootstrap that writes the broker's configuration before it first starts, a provisioner that grants each consumer its own vhost and user, a set of tools and an event consumer — all of it this module's own TypeScript, and none of it producible by naming somebody else's image. So it gets what every module with code of its own gets: a Dockerfile standing on the shared toolchain and runtime bases, a build block naming them, and containers that name the artifact rather than a digest nothing can produce. Same recipe as postgres, which is the converted module closest in shape — it has a provisioner too. Noted and deliberately not changed: postgres runs its provisioner from its container's args, and lavinmq's equivalent container names none, so on this manifest the provisioner is never started. That may be why, or may be a second fault; it is left alone so the next run says which. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
42 lines
2.5 KiB
Docker
42 lines
2.5 KiB
Docker
# lavinmq's runtime: the tool runtime, carrying this module's compiled bootstrap, provisioner,
|
|
# tools and event consumer.
|
|
#
|
|
# **Built from this module's own directory and nothing else.** The sdk is in the base image, so
|
|
# nothing is copied out of a neighbouring checkout — which is what lets the mesh build this from a
|
|
# repository and a path (novox/hq ADR 0069) rather than only on a workstation that happens to have
|
|
# the siblings.
|
|
#
|
|
# Two bases, named rather than pinned: the image this is COMPILED in, and the image it RUNS in.
|
|
# They are different images on purpose — the first carries a compiler and the second must not, or
|
|
# every running container would carry one it never invokes. The mesh answers both with the copies it
|
|
# holds, because a fingerprint written here would name one particular copy and no other mesh has it
|
|
# (novox/hq issue 044). Declared in module.json's `build.on`; deliberately no defaults, so a build
|
|
# nobody told stops here and says which module to build first.
|
|
ARG BUILD_BASE
|
|
ARG RUNTIME_BASE
|
|
|
|
FROM ${BUILD_BASE} AS build
|
|
# Compiled under /app/modules so `@novox/mesh-sdk` resolves upward into the base's own
|
|
# node_modules — the module is compiled against exactly the sdk it will run against.
|
|
WORKDIR /app/modules/lavinmq
|
|
COPY . .
|
|
# The compiler is invoked by its real path rather than through node_modules/.bin, whose entries are
|
|
# symlinks to a launcher that requires its library relatively — resolved away when the base image
|
|
# was assembled.
|
|
#
|
|
# Four entrypoints and a client, because this module is four things: a run-once bootstrap that
|
|
# writes the broker's configuration before it first starts, a provisioner that grants consumers
|
|
# their own vhost and user, a set of tools, and an event consumer.
|
|
RUN node /app/node_modules/typescript/bin/tsc \
|
|
client.ts index.ts bootstrap/index.ts provisioner/index.ts tools/index.ts \
|
|
--module NodeNext --moduleResolution NodeNext --target ES2022 --outDir dist
|
|
|
|
FROM ${RUNTIME_BASE}
|
|
COPY --from=build /app/modules/lavinmq/dist /app/modules/lavinmq/dist
|
|
# What a tool host should load from this module: its event consumer and its tools, which are
|
|
# separate entrypoints because they are loaded by different things. The bootstrap and the
|
|
# provisioner are not listed here — the declaration names each in its container's `args`, because
|
|
# they are what this module's own containers run. One image, because they are one module and share
|
|
# a client.
|
|
ENV MESH_TOOL_MODULES=/app/modules/lavinmq/dist/index.js,/app/modules/lavinmq/dist/tools/index.js
|