Installing Ticaga with Docker Compose

Author: Michael Dance

Category: Getting Started

Published: May 26, 2026

Last updated: June 1, 2026

Reading time: 11 min

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.

What the Docker Deployment Includes

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.

Requirements

Before you begin, make sure your server has:

For 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.

Step 1: Upload and Extract Ticaga

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.

Step 2: Confirm ionCube Compatibility

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.

Step 3: Create the Docker Environment File

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 Secure Values

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

Production Configuration with HTTPS

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.

Temporary Testing with a Server IP Address

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.

Step 4: Build the Ticaga 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.

Step 5: Start the Containers

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

Step 6: Complete the Web Installer

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.

Optional CLI Installation

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.

Step 7: Configure HTTPS and WebSockets for Production

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

Managing the Deployment

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.

Backups and Restore Preparation

Before updates or maintenance, back up all of the following:

Create 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.

Restore Drill

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.

Updating Ticaga

  1. Create and verify current backups of the database, stored files, and .env.docker.

  2. Stop the existing containers:

    docker compose --env-file .env.docker down
    
  3. Replace application files with the new Ticaga release while retaining .env.docker and the Docker volumes.

  4. Follow the release-specific upgrade instructions, including any required database operation, only after confirming that backups are usable.

  5. 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.

Optional Attachment Virus Scanning

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.

Troubleshooting

The Image Build Reports a Missing or Incompatible ionCube Loader

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.

The Installer Cannot Connect to MariaDB

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

The Installer Cannot Write the Environment File

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

Direct IP Testing Is Not Reachable

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

Real-Time Features Are Not Working

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