Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 115 additions & 127 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Multi-arch Dockerfile: Asterisk 20 LTS (from source) + chan_dongle
# Builds for: linux/amd64, linux/arm64, linux/arm/v7
#
# OPTIMIZED for minimal image size (~60-80 MB compressed).
# Strips binaries, drops sounds/MOH/docs, keeps only required modules.
# Uses cross-compilation for ARM targets — the builder always runs natively
# on the build platform (amd64), avoiding QEMU compiler crashes entirely.
#
# Usage:
# docker build -t asterisk-chan-dongle .
Expand All @@ -12,33 +12,44 @@
# -e TRUNK_HOST=pbx.example.com asterisk-chan-dongle
###############################################################################

# ── Stage 1: Build Asterisk 20 LTS + chan_dongle from source ────────────────
FROM debian:bookworm-slim AS builder
# Builder runs natively on the build platform (no QEMU)
FROM --platform=$BUILDPLATFORM debian:bookworm-slim AS builder

ARG TARGETARCH
ARG BUILDARCH
ARG ASTERISK_VER=20-current

# ── Install native build tools ────────────────────────────────────────────
RUN apt-get update && apt-get install -y \
build-essential \
autoconf \
automake \
libtool \
pkg-config \
ca-certificates \
wget \
bzip2 \
patch \
# Asterisk build dependencies
libncurses5-dev \
libxml2-dev \
libsqlite3-dev \
uuid-dev \
libjansson-dev \
libssl-dev \
libedit-dev \
libsrtp2-dev \
build-essential autoconf automake libtool \
pkg-config ca-certificates wget bzip2 patch \
&& rm -rf /var/lib/apt/lists/*

# ── Install target-arch compiler + libraries ──────────────────────────────
# Native build: just install dev libs directly
# Cross build: add foreign arch, install cross-compiler + target dev libs
RUN set -eux; \
if [ "$BUILDARCH" != "$TARGETARCH" ]; then \
case "$TARGETARCH" in \
arm64) DEBARCH=arm64; CROSS=aarch64-linux-gnu ;; \
arm) DEBARCH=armhf; CROSS=arm-linux-gnueabihf ;; \
*) echo "Unsupported cross target: $TARGETARCH"; exit 1 ;; \
esac; \
dpkg --add-architecture "$DEBARCH"; \
apt-get update && apt-get install -y \
gcc-${CROSS} g++-${CROSS} \
libncurses5-dev:${DEBARCH} libxml2-dev:${DEBARCH} \
libsqlite3-dev:${DEBARCH} uuid-dev:${DEBARCH} \
libjansson-dev:${DEBARCH} libssl-dev:${DEBARCH} \
libedit-dev:${DEBARCH} libsrtp2-dev:${DEBARCH}; \
else \
apt-get update && apt-get install -y \
libncurses5-dev libxml2-dev libsqlite3-dev \
uuid-dev libjansson-dev libssl-dev libedit-dev libsrtp2-dev; \
fi \
&& rm -rf /var/lib/apt/lists/*

# ── Build Asterisk 20 LTS ──────────────────────────────────────────────────
# ── Download Asterisk 20 LTS ─────────────────────────────────────────────
WORKDIR /src
RUN wget -q "https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-${ASTERISK_VER}.tar.gz" \
&& tar xzf asterisk-${ASTERISK_VER}.tar.gz \
Expand All @@ -47,64 +58,26 @@ RUN wget -q "https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-${AS

WORKDIR /src/asterisk

# QEMU emulation (used by docker buildx for arm64/armv7) can cause autoconf
# header checks to fail non-deterministically. Pre-seed all standard headers
# that are guaranteed present from our build dependencies.
RUN cat > /tmp/config.site << 'SITE'
ac_cv_header_assert_h=yes
ac_cv_header_ctype_h=yes
ac_cv_header_dlfcn_h=yes
ac_cv_header_errno_h=yes
ac_cv_header_fcntl_h=yes
ac_cv_header_float_h=yes
ac_cv_header_grp_h=yes
ac_cv_header_inttypes_h=yes
ac_cv_header_limits_h=yes
ac_cv_header_locale_h=yes
ac_cv_header_math_h=yes
ac_cv_header_pwd_h=yes
ac_cv_header_regex_h=yes
ac_cv_header_sched_h=yes
ac_cv_header_stdarg_h=yes
ac_cv_header_stdint_h=yes
ac_cv_header_stdio_h=yes
ac_cv_header_stdlib_h=yes
ac_cv_header_string_h=yes
ac_cv_header_strings_h=yes
ac_cv_header_syslog_h=yes
ac_cv_header_termios_h=yes
ac_cv_header_time_h=yes
ac_cv_header_dirent_h=yes
ac_cv_header_sys_file_h=yes
ac_cv_header_sys_ioctl_h=yes
ac_cv_header_sys_param_h=yes
ac_cv_header_sys_resource_h=yes
ac_cv_header_sys_socket_h=yes
ac_cv_header_sys_stat_h=yes
ac_cv_header_sys_time_h=yes
ac_cv_header_sys_types_h=yes
ac_cv_header_sys_un_h=yes
ac_cv_header_sys_wait_h=yes
ac_cv_header_netinet_in_h=yes
ac_cv_header_netdb_h=yes
ac_cv_header_arpa_nameser_h=yes
ac_cv_header_resolv_h=yes
ac_cv_header_sqlite3_h=yes
ac_cv_header_openssl_ssl_h=yes
ac_cv_header_openssl_crypto_h=yes
ac_cv_header_uuid_uuid_h=yes
# C/C++ compiler checks (pjproject aconfigure needs these under QEMU)
ac_cv_prog_CC=gcc
ac_cv_prog_CXX=g++
ac_cv_prog_cc_g=yes
ac_cv_prog_cxx_g=yes
ac_cv_c_compiler_gnu=yes
ac_cv_cxx_compiler_gnu=yes
SITE

RUN export CONFIG_SITE=/tmp/config.site \
&& ./configure --without-pjproject-bundled \
&& make menuselect.makeopts \
# ── Configure Asterisk ────────────────────────────────────────────────────
# Cross-compile for ARM targets; native build if architectures match.
# --without-pjproject-bundled: use system jansson, skip bundled pjproject
# (pjproject bundled build has its own configure that breaks cross-compile)
RUN set -eux; \
if [ "$BUILDARCH" != "$TARGETARCH" ]; then \
case "$TARGETARCH" in \
arm64) CROSS=aarch64-linux-gnu ;; \
arm) CROSS=arm-linux-gnueabihf ;; \
esac; \
./configure --host=${CROSS} \
CC=${CROSS}-gcc CXX=${CROSS}-g++ \
PKG_CONFIG_LIBDIR=/usr/lib/${CROSS}/pkgconfig:/usr/share/pkgconfig \
--without-pjproject-bundled; \
else \
./configure --without-pjproject-bundled; \
fi

# ── Select modules (menuselect runs on build platform natively) ───────────
RUN make menuselect.makeopts \
&& menuselect/menuselect \
--enable chan_iax2 \
--enable chan_sip \
Expand All @@ -113,70 +86,85 @@ RUN export CONFIG_SITE=/tmp/config.site \
--enable codec_g722 \
--enable res_rtp_asterisk \
--enable res_srtp \
menuselect.makeopts \
&& for attempt in 1 2 3 4 5; do \
MAKEFLAGS="-j1" CONFIG_SITE=/tmp/config.site make 2>&1 && break; \
echo ">> Build attempt $attempt failed (QEMU cc1 segfault), retrying..."; \
done \
&& make install

# ── Build chan_dongle against our Asterisk ──────────────────────────────────
menuselect.makeopts

# ── Build and install Asterisk ────────────────────────────────────────────
RUN make -j$(nproc) && make install

# ── Build chan_dongle against our Asterisk ─────────────────────────────────
COPY . /src/chan_dongle
WORKDIR /src/chan_dongle

RUN ./configure --with-asterisk=/src/asterisk/include \
RUN set -eux; \
if [ "$BUILDARCH" != "$TARGETARCH" ]; then \
case "$TARGETARCH" in \
arm64) CROSS=aarch64-linux-gnu ;; \
arm) CROSS=arm-linux-gnueabihf ;; \
esac; \
./configure --host=${CROSS} CC=${CROSS}-gcc \
--with-asterisk=/src/asterisk/include; \
else \
./configure --with-asterisk=/src/asterisk/include; \
fi \
&& make

# ── Slim down: strip binaries, drop unnecessary modules and data ──────────
RUN set -eux \
# Strip all binaries and shared libraries (huge savings, especially ARM)
&& strip /usr/sbin/asterisk \
&& strip /usr/sbin/rasterisk \
&& find /usr/lib/asterisk/modules -name '*.so' -exec strip {} + \
&& find /usr/lib -maxdepth 1 -name 'libasterisk*' -exec strip {} + \
&& strip /src/chan_dongle/chan_dongle.so \
RUN set -eux; \
if [ "$BUILDARCH" != "$TARGETARCH" ]; then \
case "$TARGETARCH" in \
arm64) STRIP=aarch64-linux-gnu-strip ;; \
arm) STRIP=arm-linux-gnueabihf-strip ;; \
esac; \
else \
STRIP=strip; \
fi; \
$STRIP /usr/sbin/asterisk; \
$STRIP /usr/sbin/rasterisk; \
find /usr/lib/asterisk/modules -name '*.so' -exec $STRIP {} +; \
find /usr/lib -maxdepth 1 -name 'libasterisk*' -exec $STRIP {} +; \
$STRIP /src/chan_dongle/chan_dongle.so; \
# ── Remove ALL data dirs we don't need ──
&& rm -rf /var/lib/asterisk/documentation \
/var/lib/asterisk/sounds \
/var/lib/asterisk/moh \
/var/lib/asterisk/static-http \
/var/lib/asterisk/rest-api \
/var/lib/asterisk/agi-bin \
/var/lib/asterisk/phoneprov \
/var/lib/asterisk/keys \
rm -rf /var/lib/asterisk/documentation \
/var/lib/asterisk/sounds \
/var/lib/asterisk/moh \
/var/lib/asterisk/static-http \
/var/lib/asterisk/rest-api \
/var/lib/asterisk/agi-bin \
/var/lib/asterisk/phoneprov \
/var/lib/asterisk/keys; \
# ── Remove modules we don't need for a GSM gateway ──
&& cd /usr/lib/asterisk/modules \
cd /usr/lib/asterisk/modules; \
# CDR/CEL backends
&& rm -f cdr_*.so cel_*.so \
rm -f cdr_*.so cel_*.so; \
# Database/directory backends
&& rm -f res_odbc*.so res_config_odbc*.so res_config_ldap*.so \
res_config_curl*.so \
rm -f res_odbc*.so res_config_odbc*.so res_config_ldap*.so \
res_config_curl*.so; \
# Services we don't use
&& rm -f res_calendar*.so res_fax*.so res_speech*.so \
res_phoneprov*.so res_adsi*.so res_smdi*.so \
res_snmp*.so res_corosync*.so res_xmpp*.so \
res_stasis*.so res_ari*.so res_http*.so \
res_musiconhold*.so res_mwi_devstate*.so \
res_parking*.so res_clioriginate*.so \
res_hep*.so res_prometheus*.so \
rm -f res_calendar*.so res_fax*.so res_speech*.so \
res_phoneprov*.so res_adsi*.so res_smdi*.so \
res_snmp*.so res_corosync*.so res_xmpp*.so \
res_stasis*.so res_ari*.so res_http*.so \
res_musiconhold*.so res_mwi_devstate*.so \
res_parking*.so res_clioriginate*.so \
res_hep*.so res_prometheus*.so; \
# Apps we don't use
&& rm -f app_voicemail*.so app_queue*.so app_confbridge*.so \
app_adsiprog*.so app_alarmreceiver*.so app_festival*.so \
app_followme*.so app_minivm*.so app_page*.so \
app_agent_pool*.so app_directory*.so \
app_meetme*.so app_mp3*.so app_skel*.so \
app_jack*.so app_morsecode*.so app_saycounted*.so \
app_statsd*.so app_test*.so \
rm -f app_voicemail*.so app_queue*.so app_confbridge*.so \
app_adsiprog*.so app_alarmreceiver*.so app_festival*.so \
app_followme*.so app_minivm*.so app_page*.so \
app_agent_pool*.so app_directory*.so \
app_meetme*.so app_mp3*.so app_skel*.so \
app_jack*.so app_morsecode*.so app_saycounted*.so \
app_statsd*.so app_test*.so; \
# Channel drivers we don't use
&& rm -f chan_mgcp*.so chan_skinny*.so chan_unistim*.so \
rm -f chan_mgcp*.so chan_skinny*.so chan_unistim*.so; \
# Test modules
&& rm -f test_*.so
rm -f test_*.so

# ── Stage 2: Slim runtime image ────────────────────────────────────────────
# ── Stage 2: Slim runtime image ──────────────────────────────────────────
FROM debian:bookworm-slim

LABEL maintainer="pulpoff"
LABEL description="Asterisk 20 LTS + chan_dongle — GSM gateway with IAX2/SIP/PJSIP support"
LABEL description="Asterisk 20 LTS + chan_dongle — GSM gateway with IAX2/SIP support"

# Runtime dependencies only (no compilers)
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand Down