# Peikarband Platform - Production Dockerfile # Multi-stage build for optimized image size and security # Build arguments ARG PYTHON_VERSION=3.11 ARG NODE_VERSION=20 ARG VERSION=latest ARG BUILD_DATE # ============================================ # Stage 1: Builder # ============================================ FROM python:${PYTHON_VERSION}-slim AS builder # Re-declare ARGs for this stage ARG NODE_VERSION=20 ARG VERSION=latest ARG BUILD_DATE LABEL maintainer="Peikarband Team " LABEL org.opencontainers.image.title="Peikarband Landing" LABEL org.opencontainers.image.description="Peikarband hosting platform landing page" LABEL org.opencontainers.image.version="${VERSION}" LABEL org.opencontainers.image.created="${BUILD_DATE}" WORKDIR /build # Install build dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ g++ \ make \ curl \ gnupg \ ca-certificates \ unzip \ && rm -rf /var/lib/apt/lists/* # Install Node.js (required for Reflex) RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* # Install bun (required by Reflex for frontend build) # Retry mechanism for network issues RUN set -ex && \ for i in 1 2 3 4 5; do \ curl -fsSL https://bun.sh/install | bash && break || \ (echo "Attempt $i failed, retrying in 5 seconds..." && sleep 5); \ done || (echo "Failed to install bun after 5 attempts" && exit 1) # Add bun to PATH ENV PATH="/root/.bun/bin:${PATH}" # Copy only requirements first (for better layer caching) COPY requirements.txt . # Install Python dependencies in user space RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \ pip install --no-cache-dir --user -r requirements.txt # Copy application code (excluding .dockerignore items) COPY --chown=root:root . . # Build and export Reflex app for production # Export creates .web directory with frontend static files # bun is now pre-installed, so reflex export won't try to download it RUN python -m reflex export --no-zip # Aggressive cleanup to reduce layer size # NOTE: Keep .web directory - it contains frontend static files RUN set -ex && \ # Remove Python cache find /build -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \ find /build -type f -name "*.pyc" -delete && \ find /build -type f -name "*.pyo" -delete && \ # Remove development files rm -rf /build/tests /build/docs /build/scripts && \ rm -rf /build/.git /build/.github /build/.vscode && \ rm -rf /build/venv /build/env && \ # Remove node_modules but KEEP .web (frontend static files) rm -rf /build/node_modules && \ # Remove large duplicate assets from root rm -f /build/*.gif /build/*.mp4 /build/*.mov 2>/dev/null || true && \ # Keep only necessary configs find /build -type f -name "docker-compose*.yml" -delete && \ find /build -type f -name "Makefile" -delete # ============================================ # Stage 2: Runtime # ============================================ FROM python:${PYTHON_VERSION}-slim # Re-declare ARGs for this stage ARG PYTHON_VERSION=3.11 ARG VERSION=latest ARG BUILD_DATE # Build info ENV VERSION=${VERSION} \ BUILD_DATE=${BUILD_DATE} WORKDIR /app # Install runtime dependencies only RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ tini \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean # Install Node.js runtime ARG NODE_VERSION=20 RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean # Create non-root user first RUN groupadd -r -g 1000 peikarband && \ useradd -r -u 1000 -g peikarband -m -s /bin/bash peikarband && \ mkdir -p /app/logs /app/uploads /app/.reflex # Copy Python dependencies from builder to user home COPY --from=builder /root/.local /home/peikarband/.local # Copy application code from builder COPY --from=builder /build /app # Fix ownership RUN chown -R peikarband:peikarband /home/peikarband/.local /app # Add version info (must be before USER switch) RUN echo "${VERSION}" > /app/.version && \ chown peikarband:peikarband /app/.version # Security: Remove unnecessary setuid/setgid permissions RUN find / -perm /6000 -type f -exec chmod a-s {} \; 2>/dev/null || true # Set environment variables ENV PATH=/home/peikarband/.local/bin:$PATH \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONHASHSEED=random \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ REFLEX_ENV=prod \ ENVIRONMENT=prod # Switch to non-root user USER peikarband # Expose ports EXPOSE 3000 8000 # Health check with better error handling HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD curl -f -s -o /dev/null -w "%{http_code}" http://localhost:8000/ping | grep -q "200" || exit 1 # Use tini as init system for proper signal handling ENTRYPOINT ["/usr/bin/tini", "--"] # Run application (both frontend and backend) CMD ["python", "-m", "reflex", "run", "--env", "prod"]