1 (206) 800-7778 [email protected]

Announcing Asterisk Docker

With WebRTC support for Odoo

Recently, I decided to setup a much more feature filled phone system, and in the open source telephony / PBX landscape there is only one serious option: Asterisk.  Given our CoreOS and Docker based infrastructure, and the fact that there is no official Asterisk Docker image, I needed to make my own Docker image to support all of the advanced features I wanted including:

  • PJSIP - The modern SIP channel driver

  • Websockets and TLS Websockets (ws://, wss://)

  • SRTP (encrypted RTP media)

  • Modern versions, e.g. 13 and 14, to test between

You can check out the repository on Github or get the image from Docker Hub.

Project Layout with docker-compose

The following docker-compose.yml is useful when testing local SIP clients, and smaller installs (the main limiting factor here being the RTP port range size).

version: '2'
services:
  asterisk:
    image: hibou/asterisk:13
    ports:
     - "5060:5060/udp"
     - "5060:5060/tcp"
     - "10000-10099:10000-10099/udp"
     - "8088:8088"
     - "8089:8089"
    volumes:
     - "./var/conf/msmtprc:/etc/msmtprc"
     - "./var/conf/asterisk:/etc/asterisk"
     - "./var/data/asterisk:/var/lib/asterisk"
     - "./var/data/asterisk-spool:/var/spool/asterisk"
    networks:
      default:
        ipv4_address: 10.3.2.10

networks:
  default:
    ipam:
      config:
      - subnet: 10.3.2.0/24

Some key points here:

  • Don’t forward too many ports to the container (RTP port range)

  • Setup a static IP range which helps to be able to reference in your configuration files

  • SIP signaling is traditionally over UDP, so you must tell docker to bind UDP when needed. (though you can use TCP)

  • RTP Ports are always over UDP

Depending on your call volume, you may need to have more RTP ports setup, or reduce the load due to forwarding ports into the container’s bridge network. A pretty typical setup has 10k ports in a range 10000-20000, and with the current Docker implementation this is impossible to do efficiently.

To achieve this, you can use "host" network mode.

version: '2'
services:
  asterisk:
    image: hibou/asterisk:13.15.0
    volumes:
     - "./var/conf/msmtprc:/etc/msmtprc"
     - "./var/conf/asterisk:/etc/asterisk"
     - "./var/data/asterisk:/var/lib/asterisk"
     - "./var/data/asterisk-spool:/var/spool/asterisk"
    hostname: sip
    domainname: sip.yourhost.name
    network_mode: "host"

With no port forwards, ensure that your configuration only binds to IP’s and ports that are necessary (e.g. if you have multiple Asterisk containers, config files must not have 0.0.0.0 in them).

Configuration

By default, Asterisk is configured heavily through configuration files. The image comes with the default configuration files from the Asterisk source code.  You can extract the sample configurations (and data directories) by binding your local folders into different directories for a single run.  So swap out the volumes in one of the above `docker-compose.yml` files for these.

    volumes:
     - "./var/conf/asterisk:/ic"
     - "./var/data/asterisk:/id"
     - "./var/data/asterisk-spool:/ids"

And then run `docker-compose run --rm asterisk bash -c “cp -R /etc/asterisk/* /ic && cp -R /var/lib/asterisk/* /id && cp -R /var/spool/asterisk/* /ids”` . This will get you in a good starting point to start your specific customizations.

At the bare minimum, you will want to spend time in the following files.

  • extensions.conf : Setup your dialplan contexts.

  • sip.conf or pjsip.conf : Setup the addresses and ports where SIP clients and trunks will communicate with your server.

  • http.conf : Setup addresses and ports for websocket based clients (e.g. Odoo Enterprise VoIP integration using sip.js for WebRTC)

Sending Mail

If you plan on sending mail (e.g. sending a user their voicemail), you will need to provide some way for Asterisk to send mail.  Asterisk uses `/etc/sbin/sendmail` to do this (and appears to be hardcoded to do so).  Given this is docker, we don’t want Postfix or some other MTA running in the server.  Instead, I have installed and symlinked msmtp to that location.  All you need to do is provide msmtp a configuration file at `/etc/msmtprc`, and msmtp will send your mail out by connecting to a SMTP server of your choice (e.g. smtp.gmail.com or smtp.mandrillapp.com).

defaults
auth on
tls on
tls_certcheck off
logfile /var/log/msmtp.log

account default
host smtp.yourhost.name
port 25
from [email protected]
user [email protected]
password pbx_user_password_here

For more information check out the msmtp project and documentation.

Data Persistence

Asterisk has two ‘data like’ folders, one at `/var/lib/asterisk` which holds media files that are commonly used to play sounds and greetings to people, as well as storing on hold music.  Typically you will record custom greetings into a path in this folder as well. It is possible to use the defaults inside the image and instead mount a custom recording directory inside of the sounds directory.

Note, if you try to record into something like ‘custom/greeting’, Asterisk will not create the folder for you, so make sure the folder exists beforehand.

The next data directory is at `/var/spool/asterisk` where call recordings and voicemail lives.

WebRTC and Odoo

One of the main reasons I wanted to do this was to be able to use the existing integration inside of Odoo Enterprise to enable a sales user to call leads in a sequential list using only their browser.

This leads to challenges beyond the typical Asterisk use cases requiring both Websockets (http.conf) to be configured, as well as special options for the dialing peers (sip.conf/pjsip.conf).  Odoo’s documentation will help here, just keep in mind that you will not be able to use the same SIP peer for a deskphone and WebRTC. Additionally, if you are running Odoo on SSL then you need even more work to get WSS and SRTP configured and working.

Note that the current version of Odoo’s sip.js is a little out of date, and has some issues communicating with PJSIP.  Using sip.js version 0.7.7 release instead has gotten me the best results so far.

Browser support is a mixed bag here, currently I have outgoing calls working with modern Safari (Technology Preview Release 33 (Safari 11.0, WebKit 12604.1.25.0.2)), Firefox (53.0.3), and Chrome (58.0.3029.110).

However, both Safari and Firefox cannot receive calls.  They start, but when you accept the call in the browser, Asterisk immediately returns from the Dial with NOANSWER.

Future

While this implementation is not perfect, I will continue looking into what can be done to improve upon this with newer versions of SIP.js and other settings changes.

If you have any Asterisk or WebRTC tips or questions, please drop me a line or comment below.

If you want to see it in action, just call us at 1-206-800-7778

Leave a comment

You must be logged in to post a comment.