Docker Compose Quickstart
The minimum useful Pipelet stack runs four containers: a database, the OCPP broker, the OCPP server, and the Headless CPMS gateway. This guide gets you from zero to a fully functioning self-hosted CPMS in about ten minutes.
What you’ll have at the end
Section titled “What you’ll have at the end” ┌─────────────────────┐ ┌───►│ cpms-headless │ REST :8080 → you │ │ (gateway) │┌────────┐ OCPP/WS ┌────────────┐ ───┘ └──────────┬──────────┘│station │◄─────────────►│ ocpp-broker│ │└────────┘ :9000 │ + ocpp- │ ◄──── shared ────┘ │ server │ MySQL └──────┬──────┘ │ ▼ ┌──────────────┐ │ MySQL 8 │ └──────────────┘Prerequisites
Section titled “Prerequisites”- Docker 24+ and Docker Compose v2 (
docker compose ..., notdocker-compose) - 2 GB free RAM, 1 GB free disk
- Ports
3306,8080, and9000available
-
Create a project directory.
Terminal window mkdir pipelet-stack && cd pipelet-stack -
Write
docker-compose.yml.services:mysql:image: mysql:8.0environment:MYSQL_ROOT_PASSWORD: changemeMYSQL_DATABASE: pipeletMYSQL_USER: pipeletMYSQL_PASSWORD: changemevolumes:- mysql-data:/var/lib/mysqlports:- "3306:3306"healthcheck:test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]interval: 5stimeout: 5sretries: 10ocpp-broker:image: ghcr.io/pipelet/ocpp-broker:latestdepends_on:mysql:condition: service_healthyenvironment:DB_HOST: mysqlDB_USER: pipeletDB_PASSWORD: changemeDB_NAME: pipeletports:- "9000:9000" # OCPP WebSocket portocpp-server:image: ghcr.io/pipelet/ocpp-server:latestdepends_on:- ocpp-brokerenvironment:DB_HOST: mysqlDB_USER: pipeletDB_PASSWORD: changemeDB_NAME: pipeletOCPP_BROKER_URL: http://ocpp-broker:9000cpms-headless:image: ghcr.io/pipelet/cpms-headless:latestdepends_on:- ocpp-serverenvironment:CPMS_API_KEY: hcpms_live_changemeOCPP_SERVER_URL: http://ocpp-server:8000DB_HOST: mysqlDB_USER: pipeletDB_PASSWORD: changemeDB_NAME: pipeletports:- "8080:8080"volumes:mysql-data: -
Start the stack.
Terminal window docker compose up -ddocker compose logs -f cpms-headlessWait for the line
Headless CPMS Gateway started on http://0.0.0.0:8080. -
Verify.
Terminal window curl -H "X-API-Key: hcpms_live_changeme" \http://localhost:8080/api/v1/system/health{ "status": "ok", "components": { "db": "ok", "broker": "ok", "ocpp_server": "ok" } } -
Connect a station. Point real or simulated charge points at:
ws://your-host:9000/{station-id}Or, for the simulator:
Terminal window docker run -d --name chargersim \-e OCPP_BACKEND_URL=ws://host.docker.internal:9000 \ghcr.io/pipelet/ocpp-chargersim:latest
Inspecting the stack
Section titled “Inspecting the stack”# Container statusdocker compose ps
# Live logs from one servicedocker compose logs -f ocpp-broker
# Hop into the MySQL shelldocker compose exec mysql mysql -upipelet -pchangeme pipelet
# Stop everything (preserves data)docker compose down
# Stop and wipe datadocker compose down -vReplacing the demo API key
Section titled “Replacing the demo API key”The demo key in the compose file (hcpms_live_changeme) is, well, demo. Generate a real one and use a .env file:
CPMS_API_KEY=hcpms_live_$(openssl rand -hex 24)MYSQL_ROOT_PASSWORD=$(openssl rand -hex 16)PIPELET_DB_PASSWORD=$(openssl rand -hex 16)Reference them in docker-compose.yml:
environment: CPMS_API_KEY: ${CPMS_API_KEY} DB_PASSWORD: ${PIPELET_DB_PASSWORD}Don’t commit .env to git. Add it to .gitignore.
Production hardening
Section titled “Production hardening”This compose file is suitable for staging and small production deployments. For a hardened setup you’ll want:
- TLS termination via a reverse proxy (Caddy, Traefik, nginx). Don’t expose
:8080and:9000directly. - PostgreSQL instead of MySQL for high-write workloads (Pipelet supports both).
- An external secrets manager. Don’t store API keys or DB passwords in the compose file.
- Separate hosts for the OCPP broker (handles long-lived connections) and the gateway (handles bursty REST traffic).
- Healthcheck-based restarts for every service, not just MySQL.
- Log shipping to your observability stack — every Pipelet service writes structured JSON logs to stdout.
What else can you run?
Section titled “What else can you run?”The 16 Pipelet modules fall into three layers:
- Core (this stack):
ocpp-broker,ocpp-server,cpms-headless,mysql/postgres. - Optional services:
cpms-ui(web dashboard),mcp-server(MCP for AI agents),automation-service+automation-studio(workflow engine),service-energy,service-cardata,service-monitoring. - Portals:
admin-portal,fleet-portal,cpms-driver-portal.
Add them one container at a time. See Modules for the full list.