Skip to main content

Docker Deployment Guide

Framework M follows a Registry-First deployment philosophy. In production, Docker images should install pre-bundled Python wheels from a registry (PyPI or a private GitLab/GitHub registry). This ensures that the image contains exactly what was tested in CI, including all backend logic and bundled frontend assets.

This lean Dockerfile is suitable for most production environments. It does not contain build tools or source code; it simply installs your application and its dependencies.

FROM python:3.12-slim-bookworm

# 1. Install runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*

# 2. Setup non-root user
RUN groupadd -r m && useradd -r -g m m
WORKDIR /app

# 3. Install Framework M and your App from a registry
# These wheels contain all necessary JS/CSS assets bundled within them
RUN pip install --no-cache-dir \
framework-m \
my-business-app \
custom-adapter-package

# 4. Security & Cleanup
RUN chown -R m:m /app
USER m

# 5. Runtime Config
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Health check using the /ready or /health endpoint
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8888/health || exit 1

EXPOSE 8888

# Start the application
ENTRYPOINT ["m"]
CMD ["start", "--host", "0.0.0.0", "--port", "8888"]

2. Why "Registry-First"?

  1. Immutability: The same wheel used in staging is deployed to production.
  2. No Build Bloat: The production image doesn't need Node.js, pnpm, or compilers.
  3. Atomic Assets: Frontend assets (Desk components, custom UI) are contained within the Python wheels and served automatically by the Litestar backend.
  4. Security: Smaller attack surface by excluding source code and build tools.

3. Environment Configuration

Framework M follows the "Everything in Env Var" policy. Pass configuration secrets using Docker secrets, Kubernetes secrets, or environment variables.

Example production .env:

DATABASE_URL=postgresql+asyncpg://user:password@db:5432/dbname
FRAMEWORK_M_JWT_SECRET=your-production-secret
INSTALLED_APPS=my_business_app,custom_adapter

4. Serving Static Assets

While the Python backend can serve assets directly, for high-scale production, we recommend using Nginx to serve the static files extracted from the wheels. See the Nginx Strategy for details.