# multistreaming — ingest one RTMP feed and restream it to many targets. # Build: docker build -t multistreaming . # Run: docker run -p 1935:1935 -p 8080:8080 -v ms_data:/data multistreaming # ---- frontend build stage ------------------------------------------------ FROM node:22-alpine AS web WORKDIR /web COPY web/package.json web/package-lock.json ./ RUN npm ci COPY web/ ./ RUN npm run build # ---- backend deps stage -------------------------------------------------- FROM node:22-alpine AS deps WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev # ---- runtime stage -------------------------------------------------------- FROM node:22-alpine WORKDIR /app # FFmpeg does the actual fan-out (remux passthrough, or re-encode for scenes). # font-dejavu is a hard runtime dependency of the drawtext text overlay filter. RUN apk add --no-cache ffmpeg font-dejavu ENV NODE_ENV=production COPY --from=deps /app/node_modules ./node_modules COPY src ./src COPY --from=web /web/dist ./web/dist # Persistent state (vaults, rooms, accounts, feeds) lives here; mount a volume. # Pre-create it and hand ownership to the runtime user so a fresh named # volume is writable without root. RUN mkdir -p /data && chown node:node /data VOLUME ["/data"] # Font paths must match where Alpine's font-dejavu installs them (the config # defaults use Debian's /usr/share/fonts/truetype/dejavu layout, which does not # exist here; drawtext only worked via a fontconfig fallback). ENV DATA_DIR=/data \ RTMP_PORT=1935 \ HTTP_PORT=8080 \ SCENE_FONT=/usr/share/fonts/dejavu/DejaVuSans.ttf \ SCENE_FONT_BOLD=/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf EXPOSE 1935 8080 USER node CMD ["node", "src/index.js"]