flopscope.
Infrastructure

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 --build

This starts two containers:

ServiceImageRole
backendDockerfile.serverRuns flopscope server, listens on IPC socket
participantDockerfile.participant-hardenedRuns 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.py

For 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.py

If 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:

  1. In-library (cooperative): BudgetContext(wall_time_limit_s=N) checks the deadline before and after each numpy call. When exceeded, it raises TimeExhaustedError with diagnostic info (which operation, elapsed time, configured limit). This is a UX feature — it gives participants a clean error message.

  2. 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.

On this page