Docker Deployment
PRISM is distributed as a container image with Chrome and all dependencies pre-installed.
Image
ghcr.io/trident-cache/prism:1.1.3
Quick Start
docker run -d \
--name prism \
-p 4000:4000 \
-v ./config.toml:/etc/prism/config.toml:ro \
-v ./license.lic:/etc/prism/license.lic:ro \
ghcr.io/trident-cache/prism:1.1.3
Docker Compose
version: "3.8"
services:
prism:
image: ghcr.io/trident-cache/prism:1.1.3
ports:
- "4000:4000"
- "4001:4001" # Admin API (optional, bind to localhost in production)
volumes:
- ./config.toml:/etc/prism/config.toml:ro
- ./license.lic:/etc/prism/license.lic:ro
environment:
- RUST_LOG=info
restart: unless-stopped
deploy:
resources:
limits:
memory: 2G
cpus: "2.0"
shm_size: "1g" # Chrome needs shared memory for rendering
security_opt:
- no-new-privileges:true
:::info Chrome Sandbox in Docker PRISM runs Chrome with sandbox enabled. The Chrome sandbox requires user namespaces, which need one of these Docker configurations (in order of preference):
-
Docker 23.0+ with host kernel
kernel.unprivileged_userns_clone=1(most secure — no extra caps needed):security_opt:- no-new-privileges:trueMost modern hosts (Ubuntu 18.04+, Fedora 31+, Debian 12+) have this enabled by default.
-
Custom seccomp profile allowing
cloneandunsharesyscalls (avoidsSYS_ADMIN):security_opt:- no-new-privileges:true- seccomp:chrome-seccomp.jsonSee the Chromium seccomp profile for reference.
-
SYS_ADMINcapability (least preferred — broadens container privileges):security_opt:- no-new-privileges:truecap_add:- SYS_ADMINAvoid
seccomp:unconfined— it disables all seccomp filtering and significantly weakens container isolation. :::
Configuration
The container's entrypoint is prism --config /etc/prism/config.toml. To use a different path, override the command (e.g. command: ["prism", "--config", "/path/to/config.toml"]).
The license path is set inside the config file ([license] path = "..."), not via an environment variable.
Environment Variables
| Variable | Description | Default |
|---|---|---|
RUST_LOG | Log level (trace, debug, info, warn, error) — overrides [logging] level | info |
Volume Mounts
| Container Path | Purpose |
|---|---|
/etc/prism/config.toml | Configuration file (path passed via --config) |
/etc/prism/license.lic | License file (path set in [license] path of config) |
Shared Memory
Chrome requires shared memory (/dev/shm) for rendering. Docker's default 64MB is insufficient and will cause Chrome to crash. Either:
- Set
shm_size: "1g"in your compose file (recommended) - Mount the host's shared memory:
-v /dev/shm:/dev/shm
Resource Limits
Recommended minimums:
| Resource | Minimum | Recommended |
|---|---|---|
| Memory | 1 GB | 2 GB |
| CPU | 1 core | 2 cores |
| Shared Memory | 512 MB | 1 GB |
Each Chrome tab uses approximately 50-150 MB of memory depending on page complexity. With the default 8 tabs, plan for at least 1.5 GB for Chrome alone.
Health Check
Add a health check to your compose file:
services:
prism:
# ...
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4001/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
Networking
In production, bind the admin API port (4001) to localhost only:
ports:
- "4000:4000" # Proxy - exposed to reverse proxy
- "127.0.0.1:4001:4001" # Admin API - localhost only
If PRISM and your origin run in the same Docker network:
services:
prism:
image: ghcr.io/trident-cache/prism:1.1.3
volumes:
- ./config.toml:/etc/prism/config.toml:ro
- ./license.lic:/etc/prism/license.lic:ro
shm_size: "1g"
networks:
- app
spa:
image: your-spa:latest
networks:
- app
networks:
app:
Then set the origin in your config to the service name:
[server]
origin = "http://spa:3000"