One image, twelve services
Section titled “One image, twelve services”Upstream ships a Dockerfile per service, but every one is the same three lines
against the same Go module: go build apps/<svc>/cmd/<svc>/main.go into a
static CGO_ENABLED=0 binary on Alpine. Publishing twelve near-identical
images would mean twelve manifest entries, twelve version.toml files and
twelve go mod download passes in CI.
This image builds every binary in a single pass — one module download, one shared build cache — and each workload picks its service explicitly:
command: ['/app/gateway']Contents: auctionhouse, authserver, charserver, chatserver, gateway,
groupserver, guidserver, guildserver, mailserver, matchmakingserver,
mysqlreverseproxy, servers-registry. Roughly 176 MB for all twelve.
There is deliberately no default entrypoint. A workload that forgets its
command: fails immediately and prints the available binaries, rather than
silently starting the wrong service.
apps/perun is excluded: it carries its own go.mod, so it is a separate
module the root build cannot resolve, and it is not part of this stack.
Why not the upstream images
Section titled “Why not the upstream images”These are built from 3kynox/ToCloud9 at f8784657, not walkline/ToCloud9.
The playerbots integration adds RPCs upstream does not implement — cluster-mode
guild creation and the guild bank. Both proto changes are purely additive
(+238/-0 and +71/-0), so protobuf wire compatibility holds and a mixed
stack degrades rather than breaks. But the worldserver does call CreateGuild,
which upstream answers UNIMPLEMENTED, so the services are built from the same
tree as the libsidecar compiled into the worldserver.
Keep this pin in lockstep with the gameserver image: libsidecar and these
services speak the gRPC contract defined in that tree’s api/proto.