acp-stack is a mono-repo that contains the services needed to run the Automated Curation Platform stack locally with Docker Compose.
Core services:
acp(automated_curation_platform) - main API and orchestration service (http://localhost:10124)aca(acp_config_assistant) - config assistant service (http://localhost:2810)mts(metadata_transformation_service) - metadata transformer service (http://localhost:1745)keycloak(acp_keycloak) - local identity provider for auth flows (http://localhost:8080)acp_postgres- PostgreSQL for ACP (localhost:5432)maildev- local SMTP + UI (http://localhost:1080, SMTPlocalhost:1025)
Observability services:
grafana(http://localhost:3000)prometheus(http://localhost:9191)loki(http://localhost:3100)promtailtempo(http://localhost:3200)
Use docker/docker-compose-full-stack.yaml to run all services.
cd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml up -d --buildcd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml pscd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml logs -fSingle service logs example:
cd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml logs -f acpcd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml restart acpcd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml downcd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml down -vThe stack includes a Locust container for load/stress testing all three core services (ACA, MTS, ACP).
docker/locustfile.py defines three user classes, one per service:
| User class | Target service | Simulated endpoints |
|---|---|---|
ACAUser |
aca (http://aca:2810) |
GET /info, GET /repositories, GET /metrics |
MTSUser |
mts (http://mts:1745) |
GET /info, GET /saved-xsl-list-only, GET /saved-xsl-list?xslt_name, GET /metrics |
ACPUser |
acp (http://acp:10124) |
GET /, GET /available-plugins, GET /metrics |
Each class uses a random wait time between 0.5 – 2 s between requests, and individual endpoints are weighted with Locust @task weights.
Why absolute URLs?
Locust's web UI has a single Host field that, when filled in, overrides thehostattribute of all user classes — causing only the matching service to receive traffic. To avoid this, every task uses a fully-qualified URL built from module-level constants (ACA,MTS,ACP) resolved from environment variables at startup. Locust's HTTP client passes absolute URLs through as-is, so all three services are tested simultaneously and the web UI Host field is ignored.
The locust service in docker-compose-full-stack.yaml starts automatically after acp, aca, and mts are healthy. Key settings:
locust:
image: locustio/locust:latest
container_name: acp_locust
ports:
- "8089:8089" # Locust web UI
volumes:
- ./locustfile.py:/mnt/locust/locustfile.py:ro
command: -f /mnt/locust/locustfile.py --users 3 --spawn-rate 1 --autostart
environment:
ACA_HOST: "http://aca:2810"
MTS_HOST: "http://mts:1745"
ACP_HOST: "http://acp:10124"The
restartdirective is intentionally commented out so Locust does not keep restarting after a test run finishes.
- Start the full stack (Locust starts together with it):
cd /Users/akmi/dev/work/dans/acp-stack/docker docker compose -f docker-compose-full-stack.yaml up -d --build - Open the Locust web UI at
http://localhost:8089. - Swarming starts automatically with defaults from compose (
--users 3 --spawn-rate 1 --autostart). - The Host field can be ignored; requests still go to
aca,mts, andacpvia absolute URLs indocker/locustfile.py. - If you stop the run in the UI, use Start to begin again with your preferred values.
Run Locust without the web UI by overriding the command:
cd /Users/akmi/dev/work/dans/acp-stack/docker
docker compose -f docker-compose-full-stack.yaml run --rm locust \
-f /mnt/locust/locustfile.py \
--headless \
--users 50 \
--spawn-rate 5 \
--run-time 2m \
--host http://acp:10124You can run Locust directly on your machine against the already-running stack:
# Install locust if needed
pip install locust
# Run from the repo root
locust -f docker/locustfile.py \
--headless \
--users 20 \
--spawn-rate 2 \
--run-time 1mThe environment variables ACA_HOST, MTS_HOST, and ACP_HOST default to the local ports (http://localhost:2810, http://localhost:1745, http://localhost:10124) when not set.
- The stack uses
docker/scripts/bootstrap-secrets.shto ensureconf/.secrets.tomlexists (copied from.secrets.toml.examplewhen missing). keycloakcan be used in combination withdans-frontend-frameworkfor local authentication integration:- After first startup, open Grafana at
http://localhost:3000.
Use these links after the full stack is running:
- Grafana home:
http://localhost:3000 - Provisioned ACP dashboard (UID
acp-observability):http://localhost:3000/d/acp-observability/acp-monitoringhttp://localhost:3000/d/acp-observability/acp-monitoring?orgId=1&refresh=5s
Default Grafana credentials (from compose):
- username:
admin - password:
admin1