10 KiB
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
- Services
- Environment Files
- Public Stack Setup
- Remote Player Setup
- Shared Secret
- Ports
- Volumes
- Networks
- Notes
- Deployment Checklist
Files
- docker-compose.yml - full public stack with web, player, player bridge, and MySQL.
- .env.example - sample environment values for the public stack.
- docker-compose.remote.yml - remote player-only stack using a published player image.
- .env.remote.example - sample environment values for the remote stack.
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_PASSWORDPULSE_SIGNAGE_SHARED_SECRETWEB_PUBLIC_URLBRIDGE_INTERNAL_URLDEFAULT_ADMIN_USERNAMEDEFAULT_ADMIN_NAMEDEFAULT_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_URLPLAYER_INTERNAL_URLPLAYER_IDENTIFIERBRIDGE_PUBLIC_URLin remote modePULSE_SIGNAGE_SHARED_SECRETWEB_PUBLIC_URLDB_HOST,DB_PORT,DB_NAME,DB_USER,DB_PASSWORDin 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_SECRETWEB_INTERNAL_URLfor the bridge when it should call the web app directly instead of inferring from request headersDB_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_NAMEDB_USERDB_PASSWORDMYSQL_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 dashboard8081- player8090- player bridge3306- 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-signagefor the public stackpulse-signage-remotefor 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_SECRETas 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_URLat the bridge, not at the public web endpoint. - The
PULSE_SIGNAGE_WEB_IMAGEandPULSE_SIGNAGE_PLAYER_IMAGEtags default to the publishedpulse-signage-webandpulse-signage-playerrepositories withlatesttags, but they can be overridden for custom releases.
Deployment Checklist
- Follow Public Stack Setup to start the public stack with Docker Compose.
- Set the same
PULSE_SIGNAGE_SHARED_SECRETin the public and remote environments. - Set
BRIDGE_PUBLIC_URLto the externally reachable bridge URL. - Start the published remote player with the workflow above.
- Verify that the player appears in Connected clients before testing screen commands.