# Multi-stage Dockerfile for Pathfinder MCP Server
# Uses uv for fast, reproducible builds
# Stage 1: Builder
FROM python:3.11-slim AS builder
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Set working directory
WORKDIR /app
# Copy dependency files and source code
COPY pyproject.toml uv.lock README.md ./
COPY src/ ./src/
# Install dependencies (frozen lock, production only)
RUN uv sync --frozen --no-dev
# Install the package itself
RUN uv pip install --no-deps .
# Stage 2: Runtime
FROM python:3.11-slim
# Create non-root user for security
RUN useradd -m -u 1000 pathfinder
# Set working directory
WORKDIR /app
# Copy virtual environment from builder
COPY --from=builder --chown=pathfinder:pathfinder /app/.venv /app/.venv
# Copy uv binary
COPY --from=builder /usr/local/bin/uv /usr/local/bin/uv
# Set environment variables
ENV PATH="/app/.venv/bin:$PATH" \
PYTHONUNBUFFERED=1 \
PATHFINDER_TRANSPORT=sse \
PATHFINDER_HOST=0.0.0.0 \
PATHFINDER_SESSIONS_DIR=/sessions
# Switch to root to ensure permissions on volume mount
USER root
# Create entrypoint script to fix permissions
RUN echo '#!/bin/sh\n\
mkdir -p /sessions\n\
chown -R pathfinder:pathfinder /sessions\n\
su pathfinder -c "pathfinder-mcp"\n\
' > /entrypoint.sh && chmod +x /entrypoint.sh
# Expose port (Railway will inject PORT env var)
EXPOSE 8000
# Health check - use environment PORT variable
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import os, http.client; port=int(os.environ.get('PORT', os.environ.get('PATHFINDER_PORT', '8000'))); conn = http.client.HTTPConnection('localhost', port); conn.request('GET', '/sse'); r = conn.getresponse(); exit(0 if r.status in (200, 404) else 1)" || exit 1
# Labels
LABEL org.opencontainers.image.title="Pathfinder MCP Server" \
org.opencontainers.image.description="FastMCP server implementing Research-Plan-Implement workflow with context compaction" \
org.opencontainers.image.version="0.1.0" \
org.opencontainers.image.source="https://github.com/jamesctucker/pathfinder-mcp"
# Entrypoint script fixes volume permissions then runs as pathfinder user
ENTRYPOINT ["/entrypoint.sh"]