This project packages Issabel 4 for Docker-based development, lab validation and production-like SIP testing using the local ISO as the source repository for installation packages. The container runs MariaDB, Apache and Asterisk in a single service, while the project workspace is mounted into the container for plugin and integration development.
- local image build from
issabel4-NIGHTLY-AST18-USB-DVD-x86_64-20211207.iso - persistent MariaDB, Asterisk config and runtime state through Docker volumes
- bridge-mode local web access on
http://127.0.0.1:8088andhttps://127.0.0.1:8443 - host-network production web access on
https://<host-or-dns>/via port443by default - host-network compose mode for production SIP/Janus traffic without Docker NAT
- mounted workspace at
/workspace - controlled sync of development assets into the Issabel runtime
- reproducible web admin credentials from
.env - guided build-time selection of Asterisk and optional RPM modules
- local module contract with reversible apply and revert on
./scripts/sync-workspace.sh
docker-compose.yml: main runtime definitiondocker-compose.hostnet.yml: production-oriented host-network runtime definitiondocker/issabel/Dockerfile: local image builddocker/issabel/rootfs/usr/local/bin/bootstrap-issabel: runtime process supervisordocker/issabel/rootfs/usr/local/bin/issabel-firstboot: first-boot and credential reconciliationdocker/issabel/rootfs/usr/local/bin/apply-issabelbr-build-assets: build-time IssabelBR package and asset integrationscripts/resolve-install-profile.py: guided installer for ISO, Asterisk package and optional modulesscripts/up.sh: build and start stackscripts/deploy-production.sh: hostnet production deploy helperscripts/build-image.sh: build image onlyscripts/down.sh: stop stackscripts/diagnose.sh: inspect processes, listeners and logsscripts/sync-workspace.sh: sync local modules and integrationsdocs/operations.md: full operational runbook
This workspace is both:
- a monorepo for Docker, bootstrap, sync, and runtime integration
- a host workspace for standalone projects that live under
modules/andoverlays/
Ownership rules:
- changes to the root repo belong to
issabel4-docker - changes inside standalone projects under
modules/oroverlays/belong to those projects, not to the monorepo - validation can use this monorepo runtime even when the source of truth is a standalone project
- publication must happen from the owning repository, never from the monorepo root
Operational rule before opening a PR:
- confirm
git rev-parse --show-toplevel - confirm
git remote -v - confirm whether the target file belongs to the monorepo or to a standalone project
The root .gitignore intentionally ignores modules/* and overlays/* so local standalone work does not leak into monorepo status, staging, or publication by accident.
- Docker daemon running locally
- Docker Compose available through
docker compose bsdtaravailable on the host- local ISO present at
issabel4-NIGHTLY-AST18-USB-DVD-x86_64-20211207.iso
Default quick start uses the lab-oriented bridge compose mode.
- Copy
.env.exampleif you want a fresh env file:cp .env.example .env - Copy
.issabel-install.conf.exampleif you want to preseed the build profile:cp .issabel-install.conf.example .issabel-install.conf - Review the runtime values in .env.
- Start the stack:
./scripts/up.sh - In interactive terminals the installer will ask for the Asterisk version first and only then show compatible optional modules.
- Open:
http://127.0.0.1:8088https://127.0.0.1:8443
The repository supports two Docker network contracts through ISSABEL_COMPOSE_MODE:
bridgeis the default lab mode and usesdocker-compose.ymlwith published portshostnetis the production-oriented mode and usesdocker-compose.hostnet.ymlwithnetwork_mode: host
Bridge mode is convenient for local web access, but it is not the correct production architecture for SIP/UDP or Janus. Docker bridge NAT and published UDP ports can rewrite or hide the real transport path, which is enough to break SIP contact addresses, re-INVITEs, RTP flow, DTMF, or Janus media even when a first registration appears to work.
Use hostnet in production, homologation, or any environment where Issabel must speak SIP/UDP directly to phones, trunks, SBCs, or Janus:
ISSABEL_COMPOSE_MODE=hostnet ./scripts/up.shThe production deploy helper uses the same contract directly:
./scripts/deploy-production.shBy default, that helper exports ISSABEL_HTTPS_PORT=443 before calling Compose, so a local .env value like 8443 does not leak into production host-network deploys. If you intentionally need another HTTPS port in hostnet mode, export either ISSABEL_HTTPS_PORT or ISSABEL_HOSTNET_HTTPS_PORT before running the script.
That helper applies the production update in this order:
- verifies that
.issabel-install.confand.build/install.envalready exist - rebuilds the
issabelimage and recreates the service inhostnet - runs
./scripts/sync-workspace.sh - shows the final service status
It intentionally does not run resolve-install-profile.py during production deploy.
Build profile resolution remains a separate preparatory step, so production deploy
does not rewrite .env or installation artifacts implicitly.
In hostnet mode Docker does not publish or NAT HTTP, HTTPS, SIP, or RTP ports. The container shares the host network stack, so peers see the host's real addresses instead of a Docker bridge address. If you deploy outside Docker host networking, the equivalent requirement is the same: no Docker bridge NAT between Issabel and the SIP or Janus peers.
Keep bridge for local lab work only:
ISSABEL_COMPOSE_MODE=bridge ./scripts/up.shUse this mode for isolated UI checks, module development, or quick local experiments where 127.0.0.1:8088 and published ports are acceptable. Do not treat successful lab registration in bridge mode as production proof for SIP or Janus.
Build-time choices are kept out of .env.
.issabel-install.confstores the selected ISO, Asterisk package and optional module keys.issabel-install.confalso stores whether the IssabelBR payload should be baked into the image build.build/install.envis generated from that profile and sourced by the build scripts- the wizard detects available
asteriskXXpackages directly from the ISO contents callcenteris shown only when the selected Asterisk package isasterisk11- the IssabelBR build payload prompt defaults to enabled for new profiles
- when enabled, the image build rewrites
CentOS-Base.repoto the AlmaLinux-hosted EL7 mirror without performing a full OS migration or upgrade - non-interactive executions reuse the saved profile instead of prompting
Current defaults are defined in .env:
COMPOSE_PROJECT_NAME=issabelISSABEL_COMPOSE_MODE=bridgeISSABEL_CONTAINER_NAME=issabel-devISSABEL_HOSTNAME=issabel.localISSABEL_HTTP_PORT=8088ISSABEL_HTTPS_PORT=8443WORKSPACE_BIND_SOURCE=.ISSABEL_WEB_ADMIN_USER=adminISSABEL_WEB_ADMIN_PASSWORD=DevAdmin123
Additionally, hostnet-oriented scripts honor ISSABEL_HOSTNET_HTTPS_PORT=443 as the production default when no explicit ISSABEL_HTTPS_PORT is exported in the shell.
ISSABEL_INSTALL_DISABLE_MOH=0
The bootstrap reconciles this web admin user into /var/www/db/acl.db on every container start. If you change these values, recreate the container:
docker compose up -d --build --force-recreate issabel
Runtime contract:
docker compose restart issabelreuses the current container and does not revisit build-time provisioningdocker compose up -d --force-recreate issabelcreates a new container and reruns only lightweight first-boot reconciliationdocker compose down && docker compose up -dalso creates a new container and therefore reruns the same lightweight reconciliation path./scripts/up.sh,./scripts/deploy-production.sh,./scripts/down.sh, and./scripts/diagnose.shresolveISSABEL_COMPOSE_MODEand pick eitherdocker-compose.ymlordocker-compose.hostnet.yml
Optional install-time patch:
- set
ISSABEL_INSTALL_DISABLE_MOH=1to apply the post-bootstrap Asterisk overrides that silence MOH for agent login and outbound pre-dial paths
The full project is mounted at /workspace inside the container. The sync helper publishes only the development targets that should affect the Issabel runtime:
/workspace/modulesto/var/www/html/modules/<module>/workspace/integrationsto/opt/issabel-integrations
This avoids bind-mounting the whole Issabel application tree over /var/www/html, which is safer for local stability.
modules/ is the safe extension point for custom Issabel changes. Most local modules stay ignored by Git, while shared wrappers can also live there as sibling repositories in the working tree when the runtime sync contract depends on them.
- a directory under
modules/becomes active when./scripts/sync-workspace.shruns - if the module contains
web/, that directory is published as/var/www/html/modules/<module> - if the customization lives under
overlays/<overlay>/web_root/, those files are applied over/var/www/htmllike a reversible theme layer - if
web/is absent, the module root is published as-is, excludingmigrations/andhooks/ - overlay conflicts on the same target path stop the sync with an explicit error
migrations/apply/<database>/*.sqlrun on sync in sorted ordermigrations/revert/<database>/*.sqlrun automatically when a module is removed and sync runs again- optional
hooks/apply.shandhooks/revert.shsupport reversible file or service changes - the
callcenter_bridgeworkspace module exposes an HTTP wrapper around ECCP for callcenter automation and panel integration when that sibling repository is present inmodules/
This keeps standalone modules separate from the stable Issabel base and makes rollback easier when a local customization causes problems. Removing the overlay directory and running sync restores the original Issabel web files that were overlaid.
The stack stores state in named Docker volumes for:
/etc/asterisk/var/lib/asterisk/var/log/asterisk/var/lib/mysql/var/spool/asterisk
That means container recreation does not wipe the PBX configuration or MariaDB state.
The container does not rely on systemd to manage services. Instead, the entrypoint starts and monitors:
mysqld_safehttpd -DFOREGROUNDasterisk -U asterisk -G asterisk -fvvvg
After Apache and Asterisk are ready, the runtime bootstrap also runs retrieve_conf plus amportal a r so generated PBX artifacts such as sip_additional.conf are rebuilt on container startup instead of depending on a manual reload.
The first-boot reconciliation also restores the IssabelPBX queues.conf include stub when the runtime file has drifted back to the stock Asterisk version, preventing queue definitions from silently disappearing even though queues_additional.conf exists.
This was chosen because it is more reliable in Docker for this Issabel 4 base than trying to reproduce a full init system inside the container.
- build only:
./scripts/build-image.sh - start or rebuild:
./scripts/up.sh - resolve or refresh the saved install profile:
python3 ./scripts/resolve-install-profile.py - stop:
./scripts/down.sh - inspect current state:
./scripts/diagnose.sh - sync local modules and apply or revert their customizations:
./scripts/sync-workspace.sh
Portainer is optional. Use it for observation only: logs, health, volumes, restarts, shell access. Do not make Portainer the source of truth for this environment. The authoritative configuration remains the selected compose file, either docker-compose.yml or docker-compose.hostnet.yml, plus .env.
The stack has been validated locally for:
- image build from the ISO-derived repository
- healthy container startup
- MariaDB readiness and seeded
asteriskcdrdb - Apache responding on port
8088 - Asterisk responding to CLI commands
- web login with credentials from
.env
For deeper operational details and troubleshooting, see docs/operations.md.