This guide explains how to deploy a new Ticaga installation with Docker Compose. The supplied deployment runs the web application, background worker, scheduler, real-time WebSocket service, and MariaDB database in containers.
Docker gives Ticaga a consistent runtime environment, but production requirements still apply: use HTTPS, restrict the installer, protect secrets, and maintain tested backups.
| Service | Purpose |
|---|---|
app |
Serves the Ticaga web application using Apache and PHP |
worker |
Processes queued background tasks |
scheduler |
Runs scheduled tasks, including configured email intake |
reverb |
Provides real-time WebSocket functionality |
db |
Runs the MariaDB database used by Ticaga |
The deployment creates persistent Docker volumes:
| Volume | Contents |
|---|---|
ticaga-db |
MariaDB database files |
ticaga-storage |
Attachments, generated files, logs, and installation state |
These volumes remain in place when application containers are stopped, restarted, or rebuilt.
Before you begin, make sure your server has:
x86_64/amd64 host for the supplied image and bundled ionCube Loaderdocker compose commandFor production, place Ticaga behind a reverse proxy or load balancer that
provides HTTPS. The supplied Compose configuration binds application ports to
127.0.0.1 by default so that a host-based proxy can reach them without
exposing unencrypted services publicly.
If you use an ARM64 host or change the PHP image, obtain a matching official ionCube Loader and validate the customised image before deployment.
Upload the Ticaga ZIP archive to your Docker host using a secure file transfer method. Extract it into your chosen deployment directory:
mkdir -p ~/ticaga
cd ~/ticaga
unzip /path/to/ticaga.zip
If the ZIP archive creates a Ticaga directory, enter it:
cd Ticaga
Verify that the Docker deployment files are present:
ls Dockerfile compose.yml .env.docker.example docker
Do not include a configured .env or .env.docker file in a downloadable
application archive. Installation secrets must be created on the target server.
The standard Ticaga Docker package includes the Linux x86_64 ionCube Loader
required by the supplied PHP 8.4 image. No separate ionCube installation is
required when using that image on a compatible host.
Confirm that the bundled loader file is present:
ls -l docker/ioncube/ioncube_loader_lin_8.4.so
If you modify the PHP version or CPU architecture, replace the loader with the matching official ionCube Loader before building the image.
Create your installation environment file:
cp .env.docker.example .env.docker
Docker Compose reads .env.docker to configure services and mounts it into
the application containers as /var/www/html/.env. Ticaga updates that file
during installation, so it must be readable by the services and writable by
the web application during initial setup.
On a Linux Docker host, assign the file to the www-data group ID used by the
supplied image and permit installation writes:
sudo chown "$(id -u)":33 .env.docker
chmod 660 .env.docker
Do not commit or share .env.docker; it contains application keys, database
passwords, and real-time service credentials.
Generate the Laravel application key using a temporary PHP container:
docker run --rm php:8.4-cli php -r "echo 'base64:'.base64_encode(random_bytes(32)).PHP_EOL;"
Generate separate random values for DB_PASSWORD, DB_ROOT_PASSWORD,
REVERB_APP_KEY, and REVERB_APP_SECRET:
openssl rand -hex 32
Edit .env.docker and set the public domain, generated secrets, and database
configuration:
APP_URL=https://support.example.com
APP_KEY=base64:REPLACE_WITH_GENERATED_APPLICATION_KEY
APP_HTTP_BIND_IP=127.0.0.1
APP_HTTP_PORT=8081
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=ticaga
DB_USERNAME=ticaga
DB_PASSWORD=REPLACE_WITH_DATABASE_PASSWORD
DB_ROOT_PASSWORD=REPLACE_WITH_ROOT_DATABASE_PASSWORD
REVERB_APP_ID=ticaga
REVERB_APP_KEY=REPLACE_WITH_REVERB_KEY
REVERB_APP_SECRET=REPLACE_WITH_REVERB_SECRET
REVERB_HOST=support.example.com
REVERB_PORT=443
REVERB_SCHEME=https
REVERB_BIND_IP=127.0.0.1
REVERB_EXTERNAL_PORT=8080
A reverse proxy installed on the Docker host should forward web traffic to
http://127.0.0.1:8081 and WebSocket traffic to http://127.0.0.1:8080.
If your proxy runs inside Docker, attach it to the application network and
route to app:80 and reverb:8080 instead of publishing ports externally.
For direct IP-based testing only, publish the ports explicitly and restrict access using your host firewall:
APP_URL=http://YOUR_SERVER_IP:8081
APP_HTTP_BIND_IP=0.0.0.0
REVERB_HOST=YOUR_SERVER_IP
REVERB_PORT=8080
REVERB_SCHEME=http
REVERB_BIND_IP=0.0.0.0
Do not use this unencrypted direct-access setup for production.
The public Reverb hostname, port, scheme, and application key are compiled into Ticaga's frontend assets during the Docker build. If these values change, rebuild the Docker image.
From the extracted application directory, build the image:
docker compose --env-file .env.docker build
The build installs dependencies, enables the bundled ionCube Loader, builds frontend assets, and configures Apache. It does not create database tables or administrator accounts.
Start the application services and database:
docker compose --env-file .env.docker up -d
docker compose --env-file .env.docker ps
If a service does not start correctly, review logs:
docker compose --env-file .env.docker logs -f
Do not make an unfinished installation publicly reachable. An untrusted visitor who reaches the setup process before you may be able to create the first administrator account.
For initial installation, use one of these approaches:
ssh -L 8081:127.0.0.1:8081 user@YOUR_SERVER_IP
Then open http://127.0.0.1:8081/install in your local browser. If you have
already configured a restricted HTTPS proxy, open
https://support.example.com/install instead.
When prompted for database details, use:
| Installer Field | Value |
|---|---|
| Database host | db |
| Database port | 3306 |
| Database name | Your DB_DATABASE value, normally ticaga |
| Database username | Your DB_USERNAME value, normally ticaga |
| Database password | Your DB_PASSWORD value |
Continue through the installer and create the first administrator account. When installation finishes, remove installer access restrictions only after the installation is confirmed complete.
Protect the environment file while retaining container read access, then recreate services so they load the final configuration:
chmod 640 .env.docker
docker compose --env-file .env.docker up -d --force-recreate
Do not use chmod 600 .env.docker with the supplied Compose deployment:
worker, scheduler, and reverb run as www-data and require read access
to the mounted file.
For a fresh install through the terminal rather than the browser, use the production image's already-built dependencies:
docker compose --env-file .env.docker exec app php artisan ticaga:install --skip-dependencies
This command creates database records and tables. Use it only for a new deployment, not as an update command for an existing production database.
The default configuration is designed for a reverse proxy running on the Docker host:
| Traffic | Proxy Destination |
|---|---|
| Web application requests | http://127.0.0.1:8081 |
| WebSocket requests | http://127.0.0.1:8080 |
Public application and Reverb values should match the HTTPS domain customers will use:
APP_URL=https://support.example.com
REVERB_HOST=support.example.com
REVERB_PORT=443
REVERB_SCHEME=https
After changing public Reverb values, rebuild and recreate the containers:
docker compose --env-file .env.docker build
docker compose --env-file .env.docker up -d --force-recreate
View container status:
docker compose --env-file .env.docker ps
View service logs:
docker compose --env-file .env.docker logs -f
Stop containers while retaining persistent data:
docker compose --env-file .env.docker down
Start the deployment again:
docker compose --env-file .env.docker up -d
Do not run docker compose --env-file .env.docker down -v during normal
maintenance. The -v option removes persistent volumes and may permanently
delete the database and uploaded files.
Before updates or maintenance, back up all of the following:
ticaga-storage volume containing uploads and runtime files.env.dockerCreate a database dump from the running database container:
mkdir -p backups
docker compose --env-file .env.docker exec -T db \
sh -c 'exec mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction --databases "$MARIADB_DATABASE"' \
> backups/ticaga-db.sql
The password is expanded inside the database container from its configured environment, rather than being placed in your host shell history.
Back up stored files through the application service, which already mounts the correct project-scoped storage volume:
docker compose --env-file .env.docker run --rm --no-deps \
-v "$PWD/backups":/backup \
app tar -czf /backup/ticaga-storage.tar.gz -C /var/www/html/storage .
cp .env.docker backups/.env.docker
chmod 600 backups/.env.docker
Retain backups outside the Docker host and test your restore procedure before applying production upgrades.
Test restoration in a separate extracted Ticaga directory with its own
Compose project name, ports, .env.docker, and empty volumes. Do not run a
restore drill over the live deployment.
After starting only the test database service, import the SQL backup:
docker compose -p ticaga-restore-test --env-file .env.docker up -d db
docker compose -p ticaga-restore-test --env-file .env.docker exec -T db \
sh -c 'exec mariadb -u root -p"$MARIADB_ROOT_PASSWORD"' \
< backups/ticaga-db.sql
Restore uploaded and generated files into the test project's newly created storage volume:
docker compose -p ticaga-restore-test --env-file .env.docker run --rm --no-deps \
-v "$PWD/backups":/backup:ro \
app sh -c 'tar -xzf /backup/ticaga-storage.tar.gz -C /var/www/html/storage && chown -R www-data:www-data /var/www/html/storage'
docker compose -p ticaga-restore-test --env-file .env.docker up -d
Verify sign-in, ticket attachments, and any required background processing in the test deployment before relying on the backup for an upgrade.
Create and verify current backups of the database, stored files, and
.env.docker.
Stop the existing containers:
docker compose --env-file .env.docker down
Replace application files with the new Ticaga release while retaining
.env.docker and the Docker volumes.
Follow the release-specific upgrade instructions, including any required database operation, only after confirming that backups are usable.
Rebuild and restart the deployment:
docker compose --env-file .env.docker build
docker compose --env-file .env.docker up -d
Never apply migrations or upgrade commands to a production database without a verified current backup.
Attachment virus scanning is disabled in the example configuration:
ATTACHMENTS_REQUIRE_VIRUS_SCAN=false
If you enable virus scanning, deploy a ClamAV service accessible from the
Ticaga worker container and configure CLAMAV_SOCKET appropriately. Do not
require scans until the worker can successfully connect to that service.
Verify that the supplied x86_64 loader is present:
ls -l docker/ioncube/ioncube_loader_lin_8.4.so
If the file is missing, restore it from the original Ticaga package. If the host is ARM64 or the PHP version changed, supply the matching official loader before building.
Use db as the database hostname, not localhost. From within an application
container, localhost refers to that container rather than MariaDB.
docker compose --env-file .env.docker ps
docker compose --env-file .env.docker logs db
On a Linux Docker host, apply installation-time group access:
sudo chown "$(id -u)":33 .env.docker
chmod 660 .env.docker
After installation:
chmod 640 .env.docker
docker compose --env-file .env.docker up -d --force-recreate
Ports bind to localhost by default. For temporary, firewall-restricted direct
testing, set these values in .env.docker and recreate containers:
APP_HTTP_BIND_IP=0.0.0.0
REVERB_BIND_IP=0.0.0.0
Confirm that the reverb container is running, that your proxy forwards
WebSocket traffic to the Reverb endpoint, and that public REVERB_HOST,
REVERB_PORT, and REVERB_SCHEME values match the customer-facing address.
Rebuild the image after changing these public settings.
docker compose --env-file .env.docker logs -f reverb
Feedback loop
Be the first to rate this guide.
Article snapshot
You can automatically close tickets that have been waiting for a customer response for more than two days by configuring the relevant department. O...
No, you do not need to purchase the updates add-on. It is only required if you would like to continue receiving updates. You can purchase the add-o...
No, you do not need to purchase the support add-on. It is only required if you would like assistance from our team during our opening hours. You can p...