Bedrud provides a multi-stage Dockerfile for building and running in containers.

Image Variants

Three image variants are published to GitHub Container Registry:

TagBaseSizeBest for
:latestDebian Bookworm~50 MBDefault — compatible with most systems
:latest-alpineAlpine 3.21~30 MBAlpine hosts, minimal footprint
:latest-distrolessDistroless~25 MBSmallest attack surface, no shell

All images contain the same static binary — the base image only affects runtime utilities (ca-certs, timezone data).

Quick Start

# Build
docker build -t bedrud .
 
# Run
docker run -d --name bedrud \
  -p 8090:8090 \
  -p 7880:7880 \
  -p 50000-60000:50000-60000/udp \
  bedrud

Dockerfile Overview

The Dockerfile uses three stages to minimize the final image size:

Stage 1: Frontend Build

FROM node:22-alpine AS frontend
RUN npm install -g bun
WORKDIR /build/apps/web
COPY apps/web/package.json apps/web/bun.lock ./
RUN bun install --frozen-lockfile
COPY apps/web/ ./
RUN bun run build:embed

Installs Bun, SSR pre-renders the React app, and copies assets to server/frontend/.

Stage 2: Server Build

FROM golang:1.25-alpine AS backend
RUN apk add --no-cache gcc musl-dev
WORKDIR /build/server
COPY server/go.mod server/go.sum ./
RUN go mod download
COPY server/ ./
COPY --from=frontend /build/server/frontend ./frontend/
RUN CGO_ENABLED=1 GOOS=linux go build -ldflags="-s -w" -o /bedrud ./cmd/bedrud/main.go
# CGO is required for SQLite (uses C bindings)

Compiles the Go binary with the frontend embedded. CGO is enabled for SQLite support (sqlite-dev provides the C headers).

Stage 3: Runtime

FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata
COPY --from=backend /bedrud /usr/local/bin/bedrud
EXPOSE 8090 7880
ENTRYPOINT ["bedrud"]
CMD ["run"]

Minimal Alpine image with just the binary, CA certificates, and timezone data.

Ports

PortServiceProtocol
8090API + Web UIHTTP
7880LiveKitWebSocket + HTTP
50000-60000RTC mediaUDP

For LiveKit media streams, you may also need to expose the RTC UDP port range (default: 50000-60000).

Volumes

Mount a volume for persistent data:

docker run -d \
  --name bedrud \
  -p 8090:8090 \
  -p 7880:7880 \
  -v bedrud-data:/var/lib/bedrud \
  bedrud

Configuration

Pass a custom configuration file:

docker run -d \
  --name bedrud \
  -p 8090:8090 \
  -p 7880:7880 \
  -v /path/to/config.yaml:/etc/bedrud/config.yaml \
  -v bedrud-data:/var/lib/bedrud \
  bedrud run --config /etc/bedrud/config.yaml

Or use environment variables:

docker run -d \
  --name bedrud \
  -p 8090:8090 \
  -p 7880:7880 \
  -e JWT_SECRET=my-production-secret \
  -e LIVEKIT_API_KEY=prodkey \
  -e LIVEKIT_API_SECRET=prodsecret \
  bedrud

TLS with Embedded LiveKit

When server TLS is enabled, the embedded LiveKit process automatically configures TURN/TLS (port 5349) using the server’s certificate. Mount your cert/key and enable TLS:

docker run -d \
  --name bedrud \
  -p 443:443 \
  -p 5349:5349 \
  -v /path/to/cert.pem:/etc/bedrud/cert.pem \
  -v /path/to/key.pem:/etc/bedrud/key.pem \
  -e SERVER_ENABLE_TLS=true \
  -e SERVER_CERT_FILE=/etc/bedrud/cert.pem \
  -e SERVER_KEY_FILE=/etc/bedrud/key.pem \
  bedrud

For a custom LiveKit YAML (advanced TURN/RTC config), mount it and set LIVEKIT_CONFIG_PATH:

docker run -d \
  --name bedrud \
  -p 8090:8090 \
  -v /path/to/livekit.yaml:/etc/bedrud/livekit.yaml \
  -e LIVEKIT_CONFIG_PATH=/etc/bedrud/livekit.yaml \
  bedrud

Pre-built Images

Docker images are published to GitHub Container Registry on every release:

# Distroless (smallest, no shell)
docker pull ghcr.io/themadorg/bedrud:latest-distroless
 
# Specific version
docker pull ghcr.io/themadorg/bedrud:v1.0.0
docker pull ghcr.io/themadorg/bedrud:v1.0.0-alpine
docker pull ghcr.io/themadorg/bedrud:v1.0.0-distroless

Docker Compose Example

services:
  bedrud:
    # Use :latest-alpine or :latest-distroless for smaller images
    image: ghcr.io/themadorg/bedrud:latest
    ports:
      - "8090:8090"
      - "7880:7880"
    volumes:
      - bedrud-data:/var/lib/bedrud
      - ./config.yaml:/etc/bedrud/config.yaml
    environment:
      - JWT_SECRET=change-me
    restart: unless-stopped
 
volumes:
  bedrud-data:

See also