This project builds a Docker container running Janus Gateway configured to:
- accept WebRTC clients over HTTP/WebSocket APIs;
- bridge media/signaling through the Janus SIP plugin to an upstream SIP server;
- keep runtime configuration environment-driven (no manual config edits in container).
The container is prepared with broad codec library support during Janus build, including common audio/video stacks used in WebRTC/SIP interop.
Dockerfile: builds Janus from source with SIP plugin and codec-related dependencies.docker/entrypoint.sh: generates Janus config files from environment variables at startup.docker-compose.yml: service definition with ports, healthcheck, and env loading..env.example: full environment template.
- Create your runtime env file:
cp .env.example .env- Edit
.envand set at least:
SIP_PROXYSIP_REGISTRARSIP_LOCAL_IP(public or reachable IP for SIP side)JANUS_NAT_1_1_MAPPING(public IP when behind NAT)
- Build and run:
docker compose up -d --build- Check health:
curl http://127.0.0.1:${JANUS_HTTP_PORT:-8088}${JANUS_HTTP_BASE_PATH:-/janus}/info8088/tcpJanus HTTP API (default)8089/tcpJanus HTTPS API (optional)8188/tcpJanus WebSocket API (default)8989/tcpJanus Secure WebSocket API (optional)5060/udplocal SIP bind for Janus SIP plugin10000-20000/udpRTP/RTCP media range
All can be changed via .env.
docker/entrypoint.sh renders these files at runtime:
/opt/janus/etc/janus/janus.jcfg/opt/janus/etc/janus/janus.transport.http.jcfg/opt/janus/etc/janus/janus.transport.websockets.jcfg/opt/janus/etc/janus/janus.plugin.sip.jcfg
That means your deployment workflow is:
- change
.env - restart container
- no hand-edited static config required
The SIP plugin supports two patterns:
- Dynamic registrations via Janus API (recommended for multi-user/browser apps)
- Single helper account in config (for quick tests), via:
SIP_ACCOUNT_USERNAMESIP_ACCOUNT_AUTHUSERSIP_ACCOUNT_SECRETSIP_PROXYSIP_REGISTRAR
The image compiles Janus with dependencies commonly required for broad codec compatibility:
- Audio: Opus, G.711 (PCMU/PCMA), G.722 and related WebRTC/SIP interoperable formats
- Video: VP8, VP9, H.264, H.265, AV1-capable library chain
Final negotiated codec set depends on:
- browser/WebRTC endpoint capabilities;
- SIP server/SBC capabilities;
- SDP offer/answer negotiation.
The workflow at .github/workflows/docker-publish.yml automatically builds for linux/amd64 and linux/arm64 using native GitHub-hosted runners, then merges both into a single multi-arch manifest list.
| Event | What happens |
|---|---|
Push to main/master |
Build both arches → push :latest + :sha-<hash> |
Push of v*.*.* tag |
Build both arches → push :1.2.3, :1.2, :1 + :latest |
| Pull request | Build both arches only (no push), layer cache preserved |
The image is published to GitHub Container Registry under:
ghcr.io/<your-org-or-user>/<repo-name>:<tag>
GITHUB_TOKEN is used automatically—no extra secrets required.
ARM64 runner note: the workflow uses
ubuntu-24.04-arm(GitHub-hosted native ARM64 runner). These are free on public repositories and available on Team/Enterprise plans for private repos. Native runners are used instead of QEMU to keep build times reasonable for a source-compiled image.
First push: GHCR packages are private by default. To make the image public, go to
https://github.com/<org>/<repo>/pkgs/container/<repo-name>→ Package settings → Change visibility.
docker pull ghcr.io/<your-org-or-user>/<repo-name>:latestOr in docker-compose.yml, replace the build: block with:
image: ghcr.io/<your-org-or-user>/<repo-name>:latest- Set
JANUS_NAT_1_1_MAPPINGwhen container is behind NAT. - Use valid certs and enable
JANUS_HTTPS_ENABLED=trueand/orJANUS_WSS_ENABLED=truefor internet-facing deployments. - Restrict exposed admin interfaces (
JANUS_ADMIN_*) unless needed. - Keep RTP UDP range open on firewall/security group.
For browser apps, Janus SIP bridging is typically consumed through Janus API clients (e.g., Janus JS integration). If your frontend is strict SIP-over-WebSocket only, add a SIP WS edge/proxy and route SIP signaling accordingly, while keeping Janus for WebRTC media/SIP bridging workflows.