Skip to content
Open
Show file tree
Hide file tree
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
92 changes: 92 additions & 0 deletions asterisk/14.7.8-alpine-3.24/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Alpine Asterisk image - installs prebuilt, signed apks from the sibling
# project's Cloudsmith repository (andrius/asterisk-alpine). There is no build
# stage: the .apk already contains the compiled, module-selected Asterisk.
# Generated from YAML configuration - DO NOT EDIT MANUALLY
FROM alpine:3.24

LABEL maintainer="Andrius Kairiukstis <k@andrius.mobi>"
LABEL org.opencontainers.image.title="Asterisk PBX"
LABEL org.opencontainers.image.description="Asterisk PBX 14.7.8 on Alpine (apk)"
LABEL org.opencontainers.image.version="14.7.8"
LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk"
LABEL org.opencontainers.image.vendor="Andrius Kairiukstis <k@andrius.mobi>"

# Trust the Cloudsmith repository signing key (vendored; copied into the build
# context alongside this Dockerfile).
COPY cloudsmith-asterisk-alpine.rsa.pub /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub

# Add the pinned apk repository and install Asterisk + the selected subpackages
# at an exact version, plus the runtime tools the entrypoint/healthcheck need.
# The @andrius-asterisk tag keeps these from clashing with Alpine's own
# asterisk in the main repo; the exact "=version-rN" pin makes rebuilds
# reproducible (or fail loudly if the apk was pruned).
RUN echo "@andrius-asterisk https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main" >>/etc/apk/repositories \
&& apk add --no-cache \
"asterisk@andrius-asterisk=14.7.8-r0" \
"asterisk-sample-config@andrius-asterisk=14.7.8-r0" \
"asterisk-opus@andrius-asterisk=14.7.8-r0" \
"asterisk-srtp@andrius-asterisk=14.7.8-r0" \
"asterisk-curl@andrius-asterisk=14.7.8-r0" \
"asterisk-speex@andrius-asterisk=14.7.8-r0" \
"asterisk-fax@andrius-asterisk=14.7.8-r0" \
"asterisk-odbc@andrius-asterisk=14.7.8-r0" \
"asterisk-mobile@andrius-asterisk=14.7.8-r0" \
"asterisk-tds@andrius-asterisk=14.7.8-r0" \
bash \
shadow \
gettext \
procps \
ca-certificates \
curl \
tzdata \
&& asterisk -V

# The asterisk apk creates the asterisk user (uid 100, home /var/lib/asterisk).
# Normalize it to the Debian image's identity (uid/gid 1000, home
# /home/asterisk, bash shell) so both image families behave identically and
# cloud/orchestration setups see a consistent uid. The entrypoint's PUID/PGID
# remap then no-ops on the default, exactly as on Debian.
RUN groupmod -g 1000 asterisk \
&& usermod -u 1000 -g 1000 -d /home/asterisk -s /bin/bash asterisk \
&& mkdir -p \
/home/asterisk \
/var/run/asterisk \
/var/log/asterisk \
/var/spool/asterisk/monitor \
/var/spool/asterisk/outgoing \
/var/spool/asterisk/tmp \
/var/spool/asterisk/voicemail \
/var/spool/asterisk/fax \
/var/lib/asterisk/keys \
/var/lib/asterisk/phoneprov \
/var/lib/asterisk/sounds \
/var/lib/asterisk/docs

# Healthcheck + entrypoint (the shared bash partials; bash + shadow are
# installed above so usermod/groupmod PUID/PGID remap works unchanged).
COPY healthcheck.sh /usr/local/bin/healthcheck.sh
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/healthcheck.sh /usr/local/bin/entrypoint.sh \
&& chown -R asterisk:asterisk \
/etc/asterisk \
/home/asterisk \
/var/lib/asterisk \
/var/log/asterisk \
/var/spool/asterisk \
/var/run/asterisk \
&& chmod -R 750 /var/spool/asterisk

# Networking (documented; publish explicitly at run time).
# EXPOSE 5060/udp
# EXPOSE 5060/tcp
# EXPOSE 10000-20000/udp
VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"]
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD /usr/local/bin/healthcheck.sh

# Entrypoint runs as root, remaps the asterisk uid/gid to PUID/PGID, then execs
# CMD. Asterisk drops privileges itself via the -U/-p flags below.
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
WORKDIR /home/asterisk
CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"]
11 changes: 11 additions & 0 deletions asterisk/14.7.8-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu5GYPGV/b1+giz7rgDN6
bkeFqT8zMHBzJ051SdVT4MbF/A6ap0hyhHDKc3o2T06Ete/vde2DjZj+RUKP1bP+
Ywamb6waQqAJsGDJ86tSsJ6eklX8N88j9Mggyx3WXu6JGrigY6i0u/7QUMXV9KAL
E2r902YoqZHn6F8FITD2VXB9NwIyMfiLsGnTmLkehhrVPupx9Qdo3URtCagYbYMh
hIScUGr1i1LKQaTSgyOCCF9sdReJuj2OT8BUuBWmIxWg4nxmx8rndllUMseYEG/q
M7dYMjLNShL6u4WNMb0hwKaYKHy69PtVBSUnLu0Y3rrH2oLo/B4XGyyX7jGw3pjx
rq1bHE2nkgGV3OjXE/ZT7oLDYZtriZHYEEdBJwFr1SHyevOlcsNqdkiskwpE/TH4
dxnIhMYJ8LYw1o5OQV6oSGpV/Mk3aYvMKyc00hZ8PjfWQkgxrkpQ4HRymp74bB1Z
M6AAzp1WcmZ3lR5ZLhAClXbwSetLrXACavIS07clOoNXAgMBAAE=
-----END PUBLIC KEY-----
59 changes: 59 additions & 0 deletions asterisk/14.7.8-alpine-3.24/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# Asterisk container entrypoint
# Generated from template for 14.7.8
#
# Adapts the in-container `asterisk` user (default uid:gid 1000:1000) to the
# uid/gid supplied via PUID / PGID env vars, then chowns runtime directories
# so bind-mounted volumes are writable. Asterisk drops privileges itself via
# its `-U asterisk -p` CMD flags, so no gosu/su-exec is needed.
#
# When the container is launched with `--user N:M` (compose `user:`), this
# script runs as that user instead of root: the adapt/chown branch is skipped
# and "$@" is exec'd as-is, matching pre-entrypoint behaviour.

set -e

PUID="${PUID:-1000}"
PGID="${PGID:-1000}"

if [ "$(id -u)" = "0" ]; then
current_uid="$(id -u asterisk)"
current_gid="$(id -g asterisk)"

if [ "$PGID" != "$current_gid" ]; then
groupmod -o -g "$PGID" asterisk
fi
if [ "$PUID" != "$current_uid" ]; then
usermod -o -u "$PUID" -g "$PGID" asterisk
fi

for path in /etc/asterisk /home/asterisk /var/lib/asterisk \
/var/log/asterisk /var/spool/asterisk /var/run/asterisk; do
[ -d "$path" ] || continue
if [ "$(stat -c '%u:%g' "$path" 2>/dev/null)" != "$PUID:$PGID" ]; then
chown -R "$PUID:$PGID" "$path" 2>/dev/null || true
fi
done
fi

# Replace the baked-in -W (light-background adjust) with whatever the user
# supplies via ASTERISK_TERMINAL_OPTS. Use cases (issue #16):
# ASTERISK_TERMINAL_OPTS="" -> drop -W, let the terminal decide
# ASTERISK_TERMINAL_OPTS="-B" -> force black background (dark terminals)
# ASTERISK_TERMINAL_OPTS="-n" -> disable colors entirely (safest in logs)
# (unset) -> keep -W (existing behaviour)
if [ -n "${ASTERISK_TERMINAL_OPTS+x}" ]; then
new_args=()
for arg in "$@"; do
if [ "$arg" = "-W" ]; then
for opt in $ASTERISK_TERMINAL_OPTS; do
new_args+=("$opt")
done
else
new_args+=("$arg")
fi
done
set -- "${new_args[@]}"
fi

exec "$@"
159 changes: 159 additions & 0 deletions asterisk/14.7.8-alpine-3.24/healthcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/bin/bash
# Asterisk health check script
# Generated from template for 14.7.8

set -euo pipefail

# Configuration
ASTERISK_CLI="/usr/sbin/asterisk -rx"
TIMEOUT=10
VERBOSE=false

# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose)
VERBOSE=true
shift
;;
-t|--timeout)
TIMEOUT="$2"
shift 2
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done

# Logging functions
log() {
if [[ "$VERBOSE" == "true" ]]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
fi
}

error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2
}

# Health check functions
check_asterisk_running() {
log "Checking if Asterisk is running..."
if ! pgrep -x asterisk >/dev/null; then
error "Asterisk process not found"
return 1
fi
log "✓ Asterisk process is running"
return 0
}

check_asterisk_responsive() {
log "Checking if Asterisk CLI is responsive..."
if ! timeout $TIMEOUT $ASTERISK_CLI "core show version" >/dev/null 2>&1; then
error "Asterisk CLI not responsive"
return 1
fi
log "✓ Asterisk CLI is responsive"
return 0
}

check_pjsip_status() {
log "Checking PJSIP status..."
if ! timeout $TIMEOUT $ASTERISK_CLI "pjsip show version" >/dev/null 2>&1; then
error "PJSIP not available or not responding"
return 1
fi
log "✓ PJSIP is available"
return 0
}

check_database_connectivity() {
log "Checking database connectivity..."
# Check if ODBC is configured and working
if ! timeout $TIMEOUT $ASTERISK_CLI "odbc show all" | grep -q "Connected" 2>/dev/null; then
log "⚠ No ODBC connections found (this may be normal)"
else
log "✓ Database connections available"
fi
return 0
}

check_essential_modules() {
log "Checking essential modules..."
local required_modules=(
"res_rtp_asterisk"
"res_timing_timerfd"
"res_crypto"
"res_pjsip"
)

for module in "${required_modules[@]}"; do
local module_output
module_output=$(timeout $TIMEOUT $ASTERISK_CLI "module show like $module" 2>&1)
if ! grep -q "$module" <<<"$module_output"; then
error "Required module $module not loaded"
return 1
fi
done
log "✓ Essential modules are loaded"
return 0
}

check_filesystem_access() {
log "Checking filesystem access..."
local required_dirs=(
"/var/log/asterisk"
"/var/spool/asterisk"
"/var/lib/asterisk"
"/etc/asterisk"
)

for dir in "${required_dirs[@]}"; do
if [[ ! -d "$dir" ]]; then
error "Required directory $dir not found"
return 1
fi
if [[ ! -r "$dir" ]]; then
error "Directory $dir not readable"
return 1
fi
done
log "✓ Filesystem access is working"
return 0
}

# Main health check
main() {
log "Starting Asterisk health check..."

local checks=(
"check_asterisk_running"
"check_asterisk_responsive"
"check_pjsip_status"
"check_database_connectivity"
"check_essential_modules"
"check_filesystem_access"
)

local failed=0
for check in "${checks[@]}"; do
if ! $check; then
failed=$((failed + 1))
fi
done

if [[ $failed -eq 0 ]]; then
log "✓ All health checks passed"
exit 0
else
error "Health check failed: $failed checks failed"
exit 1
fi
}

# Handle signals
trap 'error "Health check interrupted"; exit 1' INT TERM

main "$@"
Loading