Container image that builds and runs Asterisk with the cisco-usecallmanager patchset applied, plus defaults for SIP/PJSIP to include multiple config files. Designed to let you drop your own Asterisk config in at runtime and have variables expanded automatically.
This image with version 22.6 is not yet intended for production. See https://usecallmanager.nz/change-log.html for details regarding chan_sip backport including changes to chan_sip.
- Base OS: Debian (slim).
- Asterisk packages: built from Debian source and patched with the UseCallManager (UCM) patchset.
- Entry point: a small bootstrap script that
- remaps the runtime user if requested,
- auto-detects your public IPv4 address,
- copies any
*.conffiles from/configinto/etc/asterisk, - performs environment variable substitution (
envsubst) on those copied files (except dialplan files) - starts Asterisk.
This image consumes the patchset from the UseCallManager project:
- Site: https://usecallmanager.nz/
- Change log: https://usecallmanager.nz/change-log.html
Hints and current state as of Asterisk 22.6 (Nov 2025):
- The UCM patchset continues to evolve for Asterisk 22.x; running patched Asterisk 22.x is generally not recommended for production unless you fully understand the implications and test thoroughly.
- There have been backports and changes affecting
chan_sipin the UCM patches. Read the change log linked above and validate your configuration. chan_sipmight be suitable for connection to Cisco Phones, pjsip for other SIP endpoints.
Note: This repository’s Dockerfile currently builds against Asterisk Debian source version set by ARG ASTERISK_DEBIAN_VERSION (default in this repo points to 22.6.0 currently) on Debian Trixie.
- Docker Engine or compatible runtime.
- For external RTP media, open/forward a UDP range on your host (commonly 10000–10020) and the SIP signaling port(s) you plan to use.
- If you need lots of parallel channels increase the channel range in rtp.conf and do not use docker proxy for exposing these ports.
- Outbound DNS to resolve and query Google’s DNS (used to detect public IP) unless you override
EXTERNAL_IPyourself.
At container start, /docker-entrypoint.sh performs the following:
-
User/group remap (optional)
- If
ASTERISK_UIDandASTERISK_GIDare provided, the script recreates theasteriskuser and group with those IDs. This is useful to align file permissions with your host user when bind-mounting volumes.
- If
-
External IP detection
- The script tries to detect your public IPv4 address:
dig -4 TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's/\"//g'
- The result is exported as
EXTERNAL_IPfor later substitution. - If it cannot detect an address and you provided a
/configdirectory, the script exits with a non‑zero status. If your environment blocks that DNS query, setEXTERNAL_IPexplicitly.
- The script tries to detect your public IPv4 address:
-
Configuration files
- Configuration can be done in two ways (or also be mixed)
-
a) Config ingestion from
/config- If a directory
/configexists, every*.conffile under it is copied into/etc/asteriskpreserving relative paths. For example:/config/pjsip.conf→/etc/asterisk/pjsip.conf/config/pjsip.d/my-peer.conf→/etc/asterisk/pjsip.d/my-peer.conf
- Variable substitution is applied to all config files via
envsubst, except dialplan files:- Files matching
extensions.confor anything underextensions.d/are copied verbatim (no substitution) to avoid breaking${...}style Asterisk dialplan expressions.
- Files matching
- All other
.conffiles have shell-style variables expanded using the container’s environment (e.g.,${EXTERNAL_IP},${SIP_BIND_PORT},${WHATEVER}that you define).
- If a directory
-
b) Config through volumes files
- if you do not provider a
/configdirectory, you can also mount your own config files at runtime - volume mount your config files for SIP, PJSIP and extensions in directories /etc/asterisk/sip.d, /etc/asterisk/pjsip.d and /etc/asterisk/extensions.d.
- the main config files for SIP, PJSIP and extensions are /etc/asterisk/sip.conf, /etc/asterisk/pjsip.conf and /etc/asterisk/extensions.conf, which use a tryinclude to the mentioned subdirectories.
- if you do not provider a
-
Optional hooks
- If
/docker-entrypoint.d/exists, the script runs all executable parts usingrun-partsbefore starting Asterisk. This is handy for last-mile tweaks.
- If
-
Ownership and start
- Key Asterisk directories are chowned to the runtime user and Asterisk is launched.
Base configs are bundled under /etc/asterisk in the image (copied from this repo’s config/). Any files you place in /config will override or augment those.
All config files are defined with default values except the ones below.
For basic use cases, simply mount directory volumes to:
- /etc/asterisk/sip.d
- /etc/asterisk/pjsip.d
- /etc/asterisk/extensions.d
- /etc/asterisk/ari.d
All *.conf files there will be read. If you need more control over configs, do a volume mount to /config. Files present there will be copied to /etc/asterisk after envsubst parsing.
ari.conf- defines tryingclude ari.d/*.conf - ari disabled by defaultsip.conf- defines tryingclude sip.d/*.confpjsip.conf- defines tryingclude pjsip.d/*.confextensions.conf- defines tryingclude extensions.d/*.confasterisk.conf- defines verbose = 5, debug = 3, autosystemname = yeslogger.conf- sets logging to stdoutmodules.conf- disables modules which produce load warnings
All other config files are debian default asterisk config files. If you need to change the loaded modules, override the modules.conf file by a volume mount.
Runtime (entrypoint) variables:
ASTERISK_USER(default:asterisk)ASTERISK_GROUP(default: same as user)ASTERISK_UID/ASTERISK_GID(optional remap)EXTERNAL_IP(optional; auto-detected if not set and/configexists)- Any additional variables you define for use in your
.conffiles (expanded viaenvsubst). For example:SIP_BIND_ADDR,SIP_BIND_PORT,LOCAL_NET, etc.
Build-time (Docker build args):
DEBIAN_VERSION(default:trixie)ASTERISK_DEBIAN_VERSION(Debian source version string)PATCH_VERSION(UCM patch version, e.g.,22.6.0)
docker run \
--name asterisk \
-e EXTERNAL_IP=203.0.113.10 \ # set explicitly if autodetect is blocked
-e ASTERISK_UID=$(id -u) -e ASTERISK_GID=$(id -g) \ # optional UID/GID remap
-v $(pwd)/my-asterisk-config:/config:ro \ # configs to be processed/expanded
-p 5060:5060/udp \ # SIP signaling udp
-p 5060:5060/tcp \ # SIP signaling
-p 10000-10020:10000-10020/udp \ # RTP media range (adjust as needed)
cygnusnetworks/asterisk-usecallmanager:latest # or: ghcr.io/CygnusNetworks/asterisk-usecallmanager:latestNotes:
- If you don’t mount
/config, the image’s baked-in configs are used. - You can mount
/etc/asteriskdirectly instead, but/configis recommended so you benefit from envsubst.
services:
asterisk:
image: cygnusnetworks/asterisk-usecallmanager:latest
# image: ghcr.io/CygnusNetworks/asterisk-usecallmanager:latest # alternative image source
container_name: asterisk
environment:
# Provide EXTERNAL_IP if your DNS cannot resolve via Google’s o-o.myaddr mechanism
EXTERNAL_IP: ${EXTERNAL_IP:-}
# Optional user remap to match host user
ASTERISK_UID: ${UID:-1000}
ASTERISK_GID: ${GID:-1000}
# Any variables you reference inside your *.conf files
LOCAL_NET: 192.168.1.0/24
SIP_BIND_ADDR: 0.0.0.0
SIP_BIND_PORT: "5060"
volumes:
- ./my-asterisk-config:/config:ro
ports:
- "5060:5060/udp"
- "5060:5060/tcp"
- "10000-10020:10000-10020/udp"
restart: unless-stoppedMake sure you understand the implications of your network setup and possible ipv4 nat scenarios.
/docker-entrypoint.sh— main launcher (see “How configuration works”)./docker-entrypoint.d/— optional directory; any executable files placed here will run (viarun-parts) before Asterisk starts. Use this for last-minute file generation or tweaks.
- As of Asterisk 22.6, UCM-related features and
chan_sipchanges/backports have caveats. Review: https://usecallmanager.nz/change-log.html - Prefer
pjsipfor other SIP endpoints or sip trunks - Pin your image and config versions; test upgrades in a staging environment.
- External IP detection fails: set
EXTERNAL_IPmanually (e.g., with compose or-e). Ensure outbound DNS works if you rely on autodetect. - No audio or one-way audio: confirm RTP port range is published from host to container and your firewall/NAT rules are correct; ensure your SIP signaling advertises the correct public address (use
${EXTERNAL_IP}inpjsip.conf/sip.conf). - Variable not expanded: remember that
envsubstruns only on non-dialplan.conffiles; dialplan files (extensions.conf/extensions.d/*) are copied verbatim.
docker build \
--build-arg DEBIAN_VERSION=trixie \
--build-arg ASTERISK_DEBIAN_VERSION=22.6.0~dfsg+~cs6.15.60671435-1 \
--build-arg PATCH_VERSION=22.6.0 \
-t asterisk-usecallmanager:22.6 .Adjust the args to match versions provided by Debian and the usecallmanager patchset you want to consume. Make sure that the debian archive currently hold the ASTERISK_DEBIAN_VERSION which you specified. See: https://packages.debian.org/sid/asterisk for Debian unstable (sid) packages.
This repository contains Docker build scripts and example configs. Asterisk itself is licensed under GPLv2; consult Debian packaging and the UseCallManager project for their respective licenses.
Many thanks to the UseCallManager project for providing the patches and the maintainer Gareth Palmer.
See: https://github.com/sponsors/usecallmanagernz for sponsorship of the usecallmanager project.