Documentation Index
Fetch the complete documentation index at: https://mintlify.com/MotiaDev/motia/llms.txt
Use this file to discover all available pages before exploring further.
Docker Image
Motia provides official Docker images built with security and performance in mind:
- Base: Distroless (gcr.io/distroless/cc-debian12:nonroot)
- Runtime: Non-root user execution
- Size: Minimal attack surface (no shell, no package manager)
- Registry:
iiidev/iii:latest
Pull the Image
docker pull iiidev/iii:latest
Run Container
Basic run command:
docker run -p 3111:3111 -p 49134:49134 \
-v ./config.yaml:/app/config.yaml:ro \
iiidev/iii:latest
Exposed Ports
The Dockerfile exposes four ports:
EXPOSE 49134 3111 3112 9464
| Port | Service | Description |
|---|
| 49134 | WebSocket | Worker connections |
| 3111 | REST API | HTTP endpoints for registered functions |
| 3112 | Stream API | Real-time state synchronization |
| 9464 | Metrics | Prometheus metrics endpoint |
Docker Compose
Development Stack
The docker-compose.yml includes the full development stack with Redis and RabbitMQ:
services:
iii:
image: iiidev/iii:latest
# Or build from source instead:
# build: .
ports:
- "49134:49134" # WebSocket (worker connections)
- "3111:3111" # REST API
- "3112:3112" # Stream API
- "9464:9464" # Prometheus metrics
volumes:
- ./config.yaml:/app/config.yaml:ro
environment:
- RUST_LOG=info
depends_on:
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672" # AMQP
- "15672:15672" # Management UI
environment:
# LOCAL DEV ONLY - override in production via .env or secrets
- RABBITMQ_DEFAULT_USER=${RABBITMQ_USER:-guest}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASS:-guest}
volumes:
- rabbitmq_data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "check_running"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
redis_data:
rabbitmq_data:
Start the Stack
View Logs
docker compose logs -f iii
Stop the Stack
Production Stack with Caddy
The docker-compose.prod.yml includes Caddy as a reverse proxy with automatic HTTPS:
services:
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
iii:
condition: service_healthy
restart: unless-stopped
iii:
image: iiidev/iii:latest
volumes:
- ./config.prod.yaml:/app/config.yaml:ro
healthcheck:
test: ["CMD-SHELL", "nc -z 127.0.0.1 3111 || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
volumes:
caddy_data:
caddy_config:
Caddyfile Configuration
Create a Caddyfile for reverse proxy setup:
your-domain.com {
handle /api/* {
reverse_proxy iii:3111
}
handle /streams/* {
reverse_proxy iii:3112
}
handle /ws {
reverse_proxy iii:49134
}
handle {
reverse_proxy iii:3111
}
}
Start Production Stack
docker compose -f docker-compose.prod.yml up -d
Building from Source
Production Image
The Dockerfile uses multi-stage builds with cargo-chef for optimized layer caching:
FROM rust:slim-bookworm AS chef
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libssl-dev \
&& rm -rf /var/lib/apt/lists/* \
&& cargo install cargo-chef
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /build/recipe.json recipe.json
COPY Cargo.toml Cargo.lock ./
COPY function-macros ./function-macros
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN cargo build --release && strip target/release/iii
FROM gcr.io/distroless/cc-debian12:nonroot
COPY --from=builder /build/target/release/iii /app/iii
EXPOSE 49134 3111 3112 9464
ENTRYPOINT ["/app/iii"]
CMD ["--config", "/app/config.yaml"]
LABEL org.opencontainers.image.title="III Engine" \
org.opencontainers.image.vendor="iiidev" \
org.opencontainers.image.source="https://github.com/iii-hq/iii"
Build Locally
docker build -t iii:local .
Build Debug Image
For debugging with shell access:
docker build -f Dockerfile.debug -t iii:debug .
Volume Mounts
Configuration
Mount your config file as read-only:
-v ./config.yaml:/app/config.yaml:ro
Data Persistence
For file-based KV stores, mount a data directory:
Environment Variables
Logging
-e RUST_LOG=info # Log level: debug, info, warn, error
Configuration Expansion
The engine supports environment variable expansion in config files:
modules:
- class: modules::stream::StreamModule
config:
port: ${STREAM_PORT:3112}
adapter:
class: modules::stream::adapters::RedisAdapter
config:
redis_url: ${REDIS_URL:redis://localhost:6379}
Set via Docker:
-e STREAM_PORT=3112 \
-e REDIS_URL=redis://redis:6379
Security Hardening
For production deployments, use security options:
docker run --read-only --tmpfs /tmp \
--cap-drop=ALL --cap-add=NET_BIND_SERVICE \
--security-opt=no-new-privileges:true \
-v ./config.yaml:/app/config.yaml:ro \
-p 3111:3111 -p 49134:49134 -p 3112:3112 -p 9464:9464 \
iiidev/iii:latest
See Production Deployment for comprehensive security practices.
Next Steps
Production Setup
Security hardening and scaling strategies
Configuration
Configure modules and environment variables