Container Contract¶
Every Meridian plugin runs as a container alongside a sidecar container. This page defines the contract between them.
Environment Variables¶
Required¶
| Variable | Description | Example |
|---|---|---|
INSTANCE_ID |
Unique instance name | "oms-1", "dgm-yahoo-eod" |
POOL_TYPE |
Plugin classification | "OMSPool", "DGMPool", "SignalPool" |
Optional (Sidecar)¶
| Variable | Description | Default |
|---|---|---|
IMAGE |
Container image reference | — |
REQUESTED_GRANTS |
JSON array of {topic, action} ACL grants |
— |
TAGS |
Comma-separated capability tags | — |
SIDECAR_CONFIG |
Path to YAML config file | — |
SIDECAR_BUS_API_URL |
Bus API gRPC address | "bus-api:8443" |
Optional (Plugin)¶
| Variable | Description | Default |
|---|---|---|
SIDECAR_ADDR |
Sidecar gRPC address | "127.0.0.1:9191" |
Network Model¶
┌──────────────────────────────────────┐
│ Shared network namespace │
│ │
│ ┌─────────┐ ┌─────────────────┐ │
│ │ Plugin │───▶│ Sidecar │ │
│ │ │9191│ │──────▶ Bus API (8443)
│ └─────────┘ └─────────────────┘ │
│ │
└──────────────────────────────────────┘
- Plugin connects to sidecar on
127.0.0.1:9191only - Plugin never connects to Bus API directly
- Sidecar connects outbound to Bus API on
bus-api:8443 - Plugin and sidecar share a network namespace (
network_mode: "container:<sidecar>")
Startup Sequence¶
The sidecar performs 8 steps before accepting plugin traffic:
- Connect to Bus API
- Register instance (instance_id, pool_type, requested_grants)
- Recover ACL grants (blocks until complete)
- Recover state from durable store
- Start health check server
- Open gRPC listener on
:9191 - Accept plugin connections
- Begin message routing
Steps 1-3 and 7 are fatal — sidecar exits if they fail. Steps 4-6 are best-effort.
Health Checks¶
The sidecar exposes /healthz for Kubernetes liveness/readiness probes. The plugin must respond to on_health_check() within 5 seconds.
Graceful Shutdown¶
On SIGTERM:
- Sidecar stops accepting new messages
- Plugin receives
on_stop()callback - Plugin drains in-flight work
- Sidecar deregisters from Bus API
- Both containers exit with code 0
Docker Compose Example¶
services:
sidecar-my-plugin:
image: gitea:3000/Societal-Lab-Inc/sidecar:0.1.0
environment:
INSTANCE_ID: my-plugin
POOL_TYPE: SignalPool
SIDECAR_BUS_API_URL: bus-api:8443
networks:
- meridian
my-plugin:
build: .
network_mode: "container:sidecar-my-plugin"
environment:
SIDECAR_ADDR: "127.0.0.1:9191"
depends_on:
- sidecar-my-plugin
Dockerfile Best Practices¶
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY . .
CMD ["python", "plugin.py"]
- Use slim/alpine base images
- Install dependencies before copying source (layer caching)
- Don't run as root in production
- Don't include dev dependencies in the production image
Next Steps¶
- Deploying to Production — full deployment guide
- Conformance Tests — tests your plugin must pass