frameworks/motia/docs/content/docs/deployment-guide/docker.mdx
Docker is the foundation for all Motia production deployments. This guide covers containerizing your Motia app with the iii engine for local testing and production use.
Before creating a Docker image, build your Motia project:
motia build
This produces optimized production files:
dist/
├── index-production.js
└── index-production.js.map
Create a Dockerfile in your project root. This uses a multi-stage build to install the iii engine binary and run your Motia app with Bun:
FROM debian:bookworm-slim AS builder
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
FROM oven/bun:1.1-slim
WORKDIR /app
COPY --from=builder /root/.local/bin/iii /usr/local/bin/iii
COPY package.json .
COPY dist/index-production.js dist/
COPY dist/index-production.js.map dist/
COPY config-production.yaml config.yaml
EXPOSE 3111
EXPOSE 3112
CMD ["iii", "--config", "config.yaml"]
Create a .dockerignore to keep the image small:
node_modules
.git
.env
data/
src/
*.md
Create a config-production.yaml that uses Redis adapters for production:
modules:
- class: modules::stream::StreamModule
config:
port: ${STREAM_PORT:3112}
host: 0.0.0.0
adapter:
class: modules::stream::adapters::RedisAdapter
config:
redis_url: ${REDIS_URL:redis://localhost:6379}
- class: modules::state::StateModule
config:
adapter:
class: modules::state::adapters::RedisAdapter
config:
redis_url: ${REDIS_URL:redis://localhost:6379}
- class: modules::api::RestApiModule
config:
port: ${PORT:3111}
host: 0.0.0.0
default_timeout: 30000
concurrency_request_limit: 1024
- class: modules::queue::QueueModule
config:
adapter:
class: modules::queue::BuiltinQueueAdapter
- class: modules::observability::OtelModule
config:
enabled: ${OTEL_ENABLED:true}
service_name: ${OTEL_SERVICE_NAME:my-app}
exporter: ${OTEL_EXPORTER_TYPE:memory}
- class: modules::pubsub::PubSubModule
config:
adapter:
class: modules::pubsub::RedisAdapter
config:
redis_url: ${REDIS_URL:redis://localhost:6379}
- class: modules::cron::CronModule
config:
adapter:
class: modules::cron::KvCronAdapter
- class: modules::shell::ExecModule
config:
exec:
- bun run --enable-source-maps dist/index-production.js
For local development with Redis:
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
app:
build: .
ports:
- "3111:3111"
- "3112:3112"
environment:
- REDIS_URL=redis://redis:6379
depends_on:
- redis
Run with:
docker compose up --build
Make sure your project includes pyproject.toml and a steps/ folder
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "python-test"
version = "0.1.0"
description = "Minimal Motia Python test project"
requires-python = ">=3.10"
dependencies = [
"motia[otel]",
"iii-sdk==0.2.0",
]
[tool.hatch.build.targets.wheel]
packages = ["steps"]
Include this dockerfile
# syntax=docker/dockerfile:1
FROM debian:bookworm-slim AS iii-builder
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
FROM python:3.11-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=iii-builder /root/.local/bin/iii /usr/local/bin/iii
COPY pyproject.toml ./
COPY steps ./steps
RUN pip install --no-cache-dir uv && \
uv pip install --system .
COPY config.yaml ./config.yaml
ENV III_URL=ws://127.0.0.1:49134
EXPOSE 3111 3112
CMD ["iii", "-c", "config.yaml"]
Add a second ExecModule entry in your config-production.yaml for the Python runtime:
- class: modules::shell::ExecModule
config:
watch:
- steps/**/*_step.py
exec:
- uv run motia run --dir steps
| Port | Service |
|---|---|
3111 | REST API (HTTP endpoints) |
3112 | Stream API (WebSocket) |