Files
pulse-signage/docker-compose
lzstealth 394d23bb4d
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m15s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 32s
Release v2.13.1
2026-09-11 20:46:37 +01:00
..
2026-08-29 12:27:01 +01:00
2026-09-11 20:46:37 +01:00

Docker Compose Setup

This folder contains the Docker Compose definitions for Pulse Signage, including the public stack and the remote player stack.

Contents

Files

Stack Overview

Public stack

The main compose stack is the most complete setup. It runs:

  • web - the dashboard and admin app.
  • player - the local screen player.
  • player-bridge - the bridge service that proxies dashboard commands and player communication.
  • mysql - the database used by the web, player, and bridge services.

This is the stack to use when you want the full app running on one machine.

Remote player

The remote stack runs only the player service.

Use it when the player is installed on a remote device and connects back through the player bridge instead of running the full app separately.

Services

web

The dashboard and admin application.

Responsibilities:

  • serves the web UI on port 8080
  • reads and writes application data from MySQL
  • forwards player actions through the configured bridge base URL
  • renders connected clients, dashboard pages, and admin workflows

Key configuration:

  • DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
  • PULSE_SIGNAGE_SHARED_SECRET
  • WEB_PUBLIC_URL
  • BRIDGE_INTERNAL_URL
  • DEFAULT_ADMIN_USERNAME
  • DEFAULT_ADMIN_NAME
  • DEFAULT_ADMIN_PASSWORD

player

The screen runtime that renders playlists and receives commands.

Responsibilities:

  • serves the player UI on port 8081
  • connects to MySQL in the public stack
  • connects to the bridge in remote mode through BRIDGE_PUBLIC_URL
  • registers live connections and accepts control commands

Key configuration:

  • PLAYER_PUBLIC_URL
  • PLAYER_INTERNAL_URL
  • PLAYER_IDENTIFIER
  • BRIDGE_PUBLIC_URL in remote mode
  • PULSE_SIGNAGE_SHARED_SECRET
  • WEB_PUBLIC_URL
  • DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD in local mode

player-bridge

The bridge layer that connects the dashboard to the player network.

Responsibilities:

  • serves the bridge API on port 8090
  • forwards authenticated dashboard commands to registered players
  • exposes screen connection snapshots and player registration data
  • proxies command traffic between the web app and remote players

Key configuration:

  • PULSE_SIGNAGE_SHARED_SECRET
  • WEB_INTERNAL_URL for the bridge when it should call the web app directly instead of inferring from request headers
  • DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD

mysql

The MySQL 8.4 database used by the public stack.

Responsibilities:

  • stores application data, screen state, onboarding state, and registry records
  • provides persistent storage through mysql_data

Key configuration:

  • DB_NAME
  • DB_USER
  • DB_PASSWORD
  • MYSQL_ROOT_PASSWORD

Environment Files

File Used by How it is loaded
.env.example Public stack Copy to .env; Compose loads it automatically, or pass it with --env-file.
.env.remote.example Published remote player Copy to .env.remote; pass it with --env-file .env.remote.

The example files are templates. Copy the appropriate file, review its defaults, and replace secrets or placeholder URLs before deploying.

Public stack: .env.example

Use this file as a starting point for the public Compose stack.

Important values:

Variable Purpose Default
PULSE_SIGNAGE_WEB_IMAGE Image for the web app and bridge services. git.lzstealth.com/lzstealth/pulse-signage-web:latest
PULSE_SIGNAGE_PLAYER_IMAGE Image for the player services. git.lzstealth.com/lzstealth/pulse-signage-player:latest
PULSE_SIGNAGE_SHARED_SECRET Shared request-signing secret. Blank; set this for a secured deployment.
DB_HOST MySQL host name. mysql
DB_PORT MySQL port. 3306
DB_NAME MySQL database name. pulse-signage
DB_USER MySQL user name. pulse-signage
DB_PASSWORD MySQL user password. signage_password
MYSQL_ROOT_PASSWORD Local MySQL root password. root_password
WEB_PUBLIC_URL Public URL of the web application. http://localhost:8080
WEB_INTERNAL_URL Internal URL the bridge uses to call the web app. http://web:8080
PLAYER_INTERNAL_URL Internal URL used for local player calls. http://player:8081
PLAYER_IDENTIFIER Unique local player identifier. player-local
PLAYER_PUBLIC_URL URL used by the kiosk launcher and direct player access. http://localhost:8081
BRIDGE_INTERNAL_URL Bridge URL used for snapshots and command forwarding. http://player-bridge:8090
DEFAULT_ADMIN_USERNAME Bootstrap admin username. admin
DEFAULT_ADMIN_NAME Bootstrap admin display name. Admin
DEFAULT_ADMIN_PASSWORD Bootstrap admin password. password123!

Remote player: .env.remote.example

Use this file as the starting point for a remote player device. The production remote Compose file reads values from Compose's environment, so pass the copied file explicitly with --env-file.

Important values:

Variable Purpose Default
PULSE_SIGNAGE_PLAYER_IMAGE Image to run on the device. git.lzstealth.com/lzstealth/pulse-signage-player:latest
PULSE_SIGNAGE_SHARED_SECRET Shared request-signing secret; must match the public stack. Blank; set it to the public stack's secret.
PLAYER_IDENTIFIER Unique remote player identifier. player-remote
PLAYER_PUBLIC_URL Optional URL for direct player access. http://remote-player.example.com:8081
BRIDGE_PUBLIC_URL Bridge URL the player connects back to. http://player-bridge.example.com:8090; replace this placeholder.
PLAYER_AGENT_RECONNECT_DELAY_MS Delay before reconnecting to the bridge. 5000

Public Stack Setup

Install Docker Engine with Docker Compose, then run the public stack from this directory:

cp .env.example .env
docker compose -f docker-compose.yml up -d

The command pulls the published images, creates the network and volumes, and starts the web app, local player, player bridge, and MySQL services. Check the installation with:

docker compose -f docker-compose.yml ps
docker compose -f docker-compose.yml logs -f web

Remote Player Setup

A remote deployment has two parts:

  • the public stack runs the web app, database, and player bridge
  • each remote device runs only the player and connects back to the bridge

The remote player does not need database credentials. Set BRIDGE_PUBLIC_URL to the externally reachable bridge URL, including its port when required. It must point to the bridge service, not the web dashboard URL. The bridge must be reachable from the device and allow both HTTP requests and the player websocket connection at /ws/players.

Published remote player

On the remote device:

cp .env.remote.example .env.remote
docker compose --env-file .env.remote -f docker-compose.remote.yml up -d

The published remote stack exposes the player on host port 8081. Check its connection and startup output with:

docker compose --env-file .env.remote -f docker-compose.remote.yml ps
docker compose --env-file .env.remote -f docker-compose.remote.yml logs -f player

Start the public stack and confirm that its bridge is reachable before starting the remote player. Once the player connects, it should appear in the dashboard's Connected clients view. If it does not, verify the bridge URL, shared secret, firewall or reverse-proxy websocket support, and the player logs.

Shared Secret

This secret is the shared signing key for requests between the services. Use a single value for every service that needs to talk to the same stack, including the web app, player, bridge, and any remote player that connects back to that bridge.

Recommended shape:

  • at least 32 random bytes
  • ideally 64 hex characters, or another equally long cryptographically random string
  • not a password, phrase, or anything human-readable

If you want a quick local value, generate one with a password manager or a command such as openssl rand -hex 32.

Leave it blank only if you intentionally want to run without request signing in a throwaway local setup.

Ports

Public stack ports:

  • 8080 - web dashboard
  • 8081 - player
  • 8090 - player bridge
  • 3306 - MySQL

Remote stack ports:

  • 8081 - player only

Volumes

Public stack

  • mysql_data - persistent MySQL data.
  • pulse-signage - shared media and cache volume for the app services.

Remote stack

  • pulse-signage - shared media and cache volume for the remote player.

Networks

Each compose file creates its own named network:

  • pulse-signage for the public stack
  • pulse-signage-remote for the remote player deployment.

Notes

  • The public stack expects the web, player, and bridge services to share the same PULSE_SIGNAGE_SHARED_SECRET.
  • A remote player must use the same PULSE_SIGNAGE_SHARED_SECRET as the bridge it connects to.
  • The bridge service is the dashboard-facing command path for connected remote players.
  • The remote player should point BRIDGE_PUBLIC_URL at the bridge, not at the public web endpoint.
  • The PULSE_SIGNAGE_WEB_IMAGE and PULSE_SIGNAGE_PLAYER_IMAGE tags default to the published pulse-signage-web and pulse-signage-player repositories with latest tags, but they can be overridden for custom releases.

Deployment Checklist

  1. Follow Public Stack Setup to start the public stack with Docker Compose.
  2. Set the same PULSE_SIGNAGE_SHARED_SECRET in the public and remote environments.
  3. Set BRIDGE_PUBLIC_URL to the externally reachable bridge URL.
  4. Start the published remote player with the workflow above.
  5. Verify that the player appears in Connected clients before testing screen commands.