Overview
Cadence provides official Docker images for easy deployment. This guide covers running Cadence with Docker for both development and production environments.
Docker Images
Cadence maintains several Docker images on Docker Hub:
ubercadence/server : Standard Cadence server
ubercadence/server:master-auto-setup : Development image with automatic schema setup
ubercadence/cli : Cadence CLI tools
ubercadence/web : Web UI for workflow visualization
ubercadence/canary : Canary testing tool
ubercadence/bench : Load testing tool
The master-auto-setup image automatically sets up database schemas on startup. Use this for development only. For production, use the standard server image and manage schemas separately.
Quick Start with docker-compose
The fastest way to run Cadence locally:
Clone the repository
git clone https://github.com/cadence-workflow/cadence.git
cd cadence/docker
Start Cadence with docker-compose
This starts:
Cadence server (all services)
Cassandra database
Cadence Web UI
Prometheus for metrics
Grafana for visualization
docker-compose Configurations
Cadence provides multiple compose files for different configurations:
docker-compose.yml (Cassandra)
MySQL
PostgreSQL
ElasticSearch
services :
cassandra :
image : cassandra:4.1.1
ports :
- "9042:9042"
environment :
- "MAX_HEAP_SIZE=256M"
- "HEAP_NEWSIZE=128M"
cadence :
image : ubercadence/server:master-auto-setup
ports :
- "7933:7933" # TChannel
- "7833:7833" # gRPC
- "8000:8000" # Prometheus metrics
environment :
- "CASSANDRA_SEEDS=cassandra"
- "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000"
- "DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml"
depends_on :
- cassandra
cadence-web :
image : ubercadence/web:latest
ports :
- "8088:8088"
environment :
- "CADENCE_GRPC_PEERS=cadence:7833"
depends_on :
- cadence
Available Compose Files
File Description docker-compose.ymlCassandra + basic visibility docker-compose-mysql.ymlMySQL persistence docker-compose-postgres.ymlPostgreSQL persistence docker-compose-es.ymlCassandra + ElasticSearch 6.x docker-compose-es-v7.ymlCassandra + ElasticSearch 7.x docker-compose-opensearch.ymlCassandra + OpenSearch docker-compose-multiclusters.ymlMulti-cluster setup docker-compose-statsd.ymlStatsD metrics instead of Prometheus
MySQL Example
Complete docker-compose configuration for MySQL:
services :
mysql :
platform : linux/amd64
image : mysql:8.0
ports :
- "3306:3306"
environment :
- "MYSQL_ROOT_PASSWORD=root"
healthcheck :
test : [ "CMD" , "mysqladmin" , "ping" , "-h" , "localhost" ]
interval : 10s
timeout : 5s
retries : 5
cadence :
image : ubercadence/server:master-auto-setup
ports :
- "8000:8000"
- "8001:8001"
- "8002:8002"
- "8003:8003"
- "7933:7933"
- "7934:7934"
- "7935:7935"
- "7939:7939"
- "7833:7833"
environment :
- "DB=mysql"
- "MYSQL_USER=root"
- "MYSQL_PWD=root"
- "MYSQL_SEEDS=mysql"
- "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000"
- "PROMETHEUS_ENDPOINT_1=0.0.0.0:8001"
- "PROMETHEUS_ENDPOINT_2=0.0.0.0:8002"
- "PROMETHEUS_ENDPOINT_3=0.0.0.0:8003"
- "DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml"
depends_on :
mysql :
condition : service_healthy
cadence-web :
image : ubercadence/web:latest
environment :
- "CADENCE_GRPC_PEERS=cadence:7833"
ports :
- "8088:8088"
depends_on :
- cadence
Start with:
docker compose -f docker-compose-mysql.yml up
PostgreSQL Example
Complete docker-compose configuration for PostgreSQL:
docker-compose-postgres.yml
services :
postgres :
image : postgres:17.4
environment :
POSTGRES_USER : cadence
POSTGRES_PASSWORD : cadence
ports :
- "5432:5432"
healthcheck :
test : [ "CMD-SHELL" , "pg_isready -U cadence" ]
interval : 10s
timeout : 5s
retries : 5
cadence :
image : ubercadence/server:master-auto-setup
ports :
- "8000:8000"
- "8001:8001"
- "8002:8002"
- "8003:8003"
- "7933:7933"
- "7834:7834"
- "7935:7935"
- "7939:7939"
- "7833:7833"
environment :
- "DB=postgres"
- "DB_PORT=5432"
- "POSTGRES_USER=cadence"
- "POSTGRES_PWD=cadence"
- "POSTGRES_SEEDS=postgres"
- "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000"
- "PROMETHEUS_ENDPOINT_1=0.0.0.0:8001"
- "PROMETHEUS_ENDPOINT_2=0.0.0.0:8002"
- "PROMETHEUS_ENDPOINT_3=0.0.0.0:8003"
depends_on :
postgres :
condition : service_healthy
cadence-web :
image : ubercadence/web:latest
environment :
- "CADENCE_GRPC_PEERS=cadence:7833"
ports :
- "8088:8088"
depends_on :
- cadence
Production Docker Deployment
Using Standard Image (Recommended)
For production, use the standard server image and manage schema separately:
docker-compose-production.yml
services :
cadence-frontend :
image : ubercadence/server:1.2.7 # Use specific version tag
command :
- "/start-cadence.sh"
environment :
- "CASSANDRA_SEEDS=cassandra-prod.example.com"
- "KEYSPACE=cadence_prod"
- "VISIBILITY_KEYSPACE=cadence_visibility_prod"
- "RINGPOP_SEEDS=cadence-frontend-0:7933,cadence-frontend-1:7933"
- "SERVICES=frontend"
- "LOG_LEVEL=info"
- "NUM_HISTORY_SHARDS=4096"
- "STATSD_ENDPOINT=statsd.example.com:8125"
ports :
- "7933:7933"
- "7833:7833"
restart : unless-stopped
volumes :
- ./config:/etc/cadence/config
cadence-history :
image : ubercadence/server:1.2.7
command :
- "/start-cadence.sh"
environment :
- "CASSANDRA_SEEDS=cassandra-prod.example.com"
- "RINGPOP_SEEDS=cadence-history-0:7934,cadence-history-1:7934"
- "SERVICES=history"
- "LOG_LEVEL=info"
- "NUM_HISTORY_SHARDS=4096"
ports :
- "7934:7934"
- "7834:7834"
restart : unless-stopped
cadence-matching :
image : ubercadence/server:1.2.7
command :
- "/start-cadence.sh"
environment :
- "CASSANDRA_SEEDS=cassandra-prod.example.com"
- "RINGPOP_SEEDS=cadence-matching-0:7935,cadence-matching-1:7935"
- "SERVICES=matching"
- "LOG_LEVEL=info"
ports :
- "7935:7935"
restart : unless-stopped
cadence-worker :
image : ubercadence/server:1.2.7
command :
- "/start-cadence.sh"
environment :
- "CASSANDRA_SEEDS=cassandra-prod.example.com"
- "SERVICES=worker"
- "LOG_LEVEL=info"
ports :
- "7939:7939"
restart : unless-stopped
Environment Variables Reference
Key environment variables for Docker deployment:
Variable Description Default DBDatabase type: cassandra, mysql, postgres cassandra CASSANDRA_SEEDSCassandra seed nodes (CSV) - MYSQL_SEEDSMySQL host - POSTGRES_SEEDSPostgreSQL host - KEYSPACE / DBNAMEDatabase/keyspace name cadence VISIBILITY_KEYSPACEVisibility store name cadence_visibility NUM_HISTORY_SHARDSNumber of history shards 4 RINGPOP_SEEDSCluster membership seeds (CSV) - SERVICESServices to run (CSV) history,matching,frontend,worker LOG_LEVELLogging level info STATSD_ENDPOINTStatsD server - PROMETHEUS_ENDPOINT_0Prometheus metrics address - ENABLE_ESEnable ElasticSearch false ES_SEEDSElasticSearch seeds - DYNAMIC_CONFIG_FILE_PATHDynamic config file path /etc/cadence/config/dynamicconfig/development.yaml
Volumes and Persistence
Mount configuration files and data directories:
services :
cadence :
volumes :
# Custom configuration
- ./config:/etc/cadence/config:ro
# Dynamic config (read-write for updates)
- ./dynamicconfig:/etc/cadence/config/dynamicconfig
# TLS certificates
- ./certs:/etc/cadence/certs:ro
# File-based archival
- ./archival:/tmp/cadence_archival
Building Custom Images
Build Standard Server Image
git clone https://github.com/cadence-workflow/cadence.git
cd cadence
# Build server image
docker build . -t mycorp/cadence-server:v1.0.0 \
--build-arg TARGET=server
# Build auto-setup image for development
docker build . -t mycorp/cadence-server:v1.0.0-auto-setup \
--build-arg TARGET=auto-setup
# Build CLI image
docker build . -t mycorp/cadence-cli:v1.0.0 \
--build-arg TARGET=cli
Multi-stage Dockerfile Structure
The Cadence Dockerfile uses multi-stage builds:
ARG TARGET=server
# Stage 1: Build binaries
FROM golang:1.23.4-alpine3.21 AS builder
WORKDIR /cadence
COPY . .
RUN make cadence-server cadence-cassandra-tool cadence-sql-tool
# Stage 2: Base server image
FROM alpine:3.18 AS cadence-server
COPY --from=builder /cadence/cadence-server /usr/local/bin
COPY --from=builder /cadence/schema /etc/cadence/schema
COPY docker/start-cadence.sh /start-cadence.sh
EXPOSE 7933 7934 7935 7939
CMD [ "/start-cadence.sh" ]
# Stage 3: Auto-setup image (includes schema tools)
FROM cadence-server AS cadence-auto-setup
RUN apk add --no-cache mysql-client
RUN pip3 install cqlsh
COPY docker/start.sh /start.sh
CMD [ "/start.sh" ]
# Final stage selected by TARGET arg
FROM cadence-${TARGET}
Testing and Development
Running Locally with Custom Code
Test custom server code with Docker dependencies:
Start dependencies only
docker compose up cassandra prometheus grafana
Build and run local server
make bins
./cadence-server start
Running Tests with Docker
Use docker-compose for integration tests:
# Start test environment
cd docker/github_actions
docker compose -f docker-compose-local.yml up
# Run tests
make test
Monitoring and Observability
Prometheus Metrics
Cadence exposes Prometheus metrics on each service:
services :
cadence :
environment :
- "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000" # Frontend
- "PROMETHEUS_ENDPOINT_1=0.0.0.0:8001" # Matching
- "PROMETHEUS_ENDPOINT_2=0.0.0.0:8002" # History
- "PROMETHEUS_ENDPOINT_3=0.0.0.0:8003" # Worker
Access metrics:
curl http://localhost:8000/metrics
Grafana Dashboards
The docker-compose setup includes pre-configured Grafana dashboards:
services :
grafana :
image : grafana/grafana
volumes :
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/provisioning/dashboards:/var/lib/grafana/dashboards
ports :
- '3000:3000'
Included dashboards:
Cadence Server Overview
Frontend Service Metrics
History Service Metrics
Matching Service Metrics
Persistence Metrics
Troubleshooting
Container Won’t Start
# Check container logs
docker compose logs cadence
# Check if database is ready
docker compose logs cassandra
# Verify network connectivity
docker compose exec cadence ping cassandra
Database Connection Issues
# Test Cassandra connection
docker compose exec cadence cqlsh cassandra -e "describe keyspaces"
# Test MySQL connection
docker compose exec cadence mysql -h mysql -u root -proot -e "show databases"
# Test PostgreSQL connection
docker compose exec cadence psql -h postgres -U cadence -c "\l"
Schema Not Created
If using auto-setup image and schema isn’t created:
# Check startup logs for schema setup
docker compose logs cadence | grep -i schema
# Manually run schema setup
docker compose exec cadence bash
cadence-cassandra-tool --ep cassandra create --keyspace cadence
Increase container resources:
services :
cadence :
deploy :
resources :
limits :
cpus : '2'
memory : 4G
Tune database container:
cassandra :
environment :
- "MAX_HEAP_SIZE=2G"
- "HEAP_NEWSIZE=512M"
Production Best Practices
Use specific version tags
Never use latest or master tags in production: image : ubercadence/server:1.2.7 # Good
image : ubercadence/server:latest # Bad
Separate services
Run each service type in separate containers for better scaling: cadence-frontend :
environment :
- "SERVICES=frontend"
cadence-history :
environment :
- "SERVICES=history"
Use external databases
Don’t run production databases in containers. Use managed database services.
Configure health checks
cadence :
healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:8000/health" ]
interval : 30s
timeout : 10s
retries : 3
Set resource limits
deploy :
resources :
limits :
cpus : '2'
memory : 4G
reservations :
cpus : '1'
memory : 2G
Next Steps
Kubernetes Deployment Deploy Cadence on Kubernetes
Configuration Advanced configuration options