# Dragon Fork datarhei Core image (M2 + WebRTC egress). # # Builds the real root Core binary — the one that replaces the M1 PoC # in production. FFmpeg is baked in so restream processes can run the # RTP output legs emitted by the WebRTC subsystem. # # Two-stage: # 1. builder: compile a static Go binary (CGO off — no dynamic libs) # 2. ui-builder: clone wilddragon-restreamer-ui, apply its overlay on # top of upstream datarhei/restreamer-ui v1.14.0, yarn build. # See https://forge.wilddragon.net/zgaetano/wilddragon-restreamer-ui # 3. runtime: alpine with ffmpeg for the subprocess path # # Usage via compose: # docker compose -f deploy/truenas/core/docker-compose.yml up -d --build # # The compose file drives configuration via CORE_* env vars — see # README.md in this directory. # ---- builder ---- # go.mod requires go 1.24; pinning the image keeps Docker's toolchain # download off the hot path and makes the build reproducible. FROM golang:1.24-alpine3.20 AS builder WORKDIR /src RUN apk add --no-cache git make COPY . . ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 RUN make release && make import && make ffmigrate # ---- ui-builder ---- # Clones wilddragon-restreamer-ui (the Wild Dragon UI fork) which # provides apply-overlay.sh and all overlay files (branding, WebRTC # WHEP controls). Then clones upstream restreamer-ui at the pinned # tag, applies the overlay, and runs yarn build. # # WD_UI_REF: branch or tag in wilddragon-restreamer-ui to build from. # RESTREAMER_UI_REF: upstream datarhei/restreamer-ui tag to base on. FROM node:21-alpine3.20 AS ui-builder ARG WD_UI_REF=main ARG RESTREAMER_UI_REF=v1.14.0 RUN apk add --no-cache git # Wild Dragon UI fork: overlay files + apply-overlay.sh RUN git clone --depth=1 --branch ${WD_UI_REF} \ https://forge.wilddragon.net/zgaetano/wilddragon-restreamer-ui.git /wd-ui # Upstream React SPA at the pinned version RUN git clone --depth=1 --branch ${RESTREAMER_UI_REF} \ https://github.com/datarhei/restreamer-ui.git /ui WORKDIR /ui RUN yarn install --frozen-lockfile --network-timeout 600000 # Apply Wild Dragon branding + WebRTC controls. # chmod is required because git may clone the script without +x. RUN chmod +x /wd-ui/apply-overlay.sh && \ OVERLAY=/wd-ui/overlay UI=/ui /wd-ui/apply-overlay.sh RUN PUBLIC_URL="./" GENERATE_SOURCEMAP=false yarn build # ---- runtime ---- # Alpine with ffmpeg (Core shells out to it for every restream process). # Scratch isn't an option here because the process manager needs ffmpeg # on PATH. FROM alpine:3.20 AS runtime RUN apk add --no-cache ffmpeg tini ca-certificates # make release's `-o core` lands the binary inside the core/ Go # package directory (Go cannot overwrite a directory with a file, so # it places the output file _inside_ it). The `import` and `ffmigrate` # Makefile targets cd into app/ and write the binary back up to # the repo root with a relative path, so those end up at /src/import # and /src/ffmigrate. COPY --from=builder /src/core/core /core/bin/core COPY --from=builder /src/import /core/bin/import COPY --from=builder /src/ffmigrate /core/bin/ffmigrate COPY --from=builder /src/mime.types /core/mime.types COPY --from=builder /src/run.sh /core/bin/run.sh # Static content for /core/data, seeded on first boot by seed-data.sh. # Stacking order: # 1. Restreamer UI bundle (the React SPA — gives us index.html) # 2. Dragon Fork extras (whep-player.html, etc.) — won't overwrite # the UI's index.html (seed-data is no-clobber). # # The result: GET / serves the Wild Dragon dashboard, and # /whep-player.html serves the standalone WHEP smoke player. COPY --from=ui-builder /ui/build/ /core/static/ COPY --from=builder /src/deploy/truenas/core/static/ /core/static/ COPY --from=builder /src/deploy/truenas/core/seed-data.sh /core/bin/seed-data.sh RUN chmod +x /core/bin/seed-data.sh && mkdir -p /core/config /core/data ENV CORE_CONFIGFILE=/core/config/config.json ENV CORE_STORAGE_DISK_DIR=/core/data ENV CORE_DB_DIR=/core/config VOLUME ["/core/data", "/core/config"] EXPOSE 8080/tcp # Seed /core/data on first boot, then exec the upstream run.sh which # handles imports, ffmpeg migrations, and the core binary. tini reaps # child PIDs and forwards signals. ENTRYPOINT ["/sbin/tini", "--", "/bin/sh", "-c", "/core/bin/seed-data.sh && exec /core/bin/run.sh"] WORKDIR /core