Running with Docker
Use this page to run the client-server model locally, either with Docker Compose or manually.
You will learn:
- How to start the client-server setup with Docker Compose
- How to run client and server manually without Docker
- How to configure IPC and TCP transports
Prerequisites
- Client-Server Model — understand why the architecture exists
- Docker and Docker Compose installed
With Docker Compose
The docker/ directory contains a ready-to-use setup:
cd docker
docker compose up --buildThis starts two containers:
| Service | Image | Role |
|---|---|---|
backend | Dockerfile.server | Runs flopscope server, listens on IPC socket |
participant | Dockerfile.participant-hardened | Runs participant code with flopscope-client only |
The containers share an IPC socket volume for communication.
Without Docker
From a source checkout, start both processes from the repository root so the
server can import the local src/flopscope package:
# Terminal 1: Start the server
PYTHONPATH=src:flopscope-server/src \
uv run --with pyzmq --with msgpack \
python -m flopscope_server --url ipc:///tmp/flopscope.sock# Terminal 2: Run client code
export FLOPSCOPE_SERVER_URL=ipc:///tmp/flopscope.sock
PYTHONPATH=flopscope-client/src \
uv run --with pyzmq --with msgpack python your_script.pyFor TCP (e.g., across machines):
# Server
PYTHONPATH=src:flopscope-server/src \
uv run --with pyzmq --with msgpack \
python -m flopscope_server --url tcp://0.0.0.0:15555
# Client
export FLOPSCOPE_SERVER_URL=tcp://server-host:15555
PYTHONPATH=flopscope-client/src \
uv run --with pyzmq --with msgpack python your_script.pyIf you already have flopscope-client and flopscope-server installed into
separate environments, the shorter cd ... && uv run ... workflow also works.
The commands above are the reproducible source-checkout path.
Time limit enforcement
Submissions run under two layers of time enforcement:
-
In-library (cooperative):
BudgetContext(wall_time_limit_s=N)checks the deadline before and after each numpy call. When exceeded, it raisesTimeExhaustedErrorwith diagnostic info (which operation, elapsed time, configured limit). This is a UX feature — it gives participants a clean error message. -
Container-level (hard): The Docker container enforces a kernel-level time limit via cgroups/rlimit. If the in-library check doesn't catch the overshoot (e.g., a single very long numpy call), the container delivers
SIGKILL. This is the ultimate backstop — no Python code can escape it.
Signal-based preemption (SIGALRM) is deliberately not used because Python signal handlers cannot interrupt C extensions (numpy/LAPACK/BLAS), making them ineffective for exactly the operations where time limits matter most.
Common pitfalls
Symptom: Connection refused or timeout
Fix: Ensure the server is running before starting the client. Check that FLOPSCOPE_SERVER_URL matches the server's --url argument.
Symptom: Port conflict
Fix: Change the port in both the server --url and client FLOPSCOPE_SERVER_URL.
Related pages
- Client-Server Model — architecture overview
- Contributor Guide — local repo workflows