# syntax=docker/dockerfile:1.5 # Production Dockerfile for Delphi Consulting Group Database System ARG BASE_IMAGE=python:3.12-slim FROM ${BASE_IMAGE} as builder # Set build arguments ARG BUILD_DATE ARG VERSION ARG VCS_REF # Install build dependencies RUN apt-get update \ && apt-get install -y --no-install-recommends \ gcc \ g++ \ build-essential \ && rm -rf /var/lib/apt/lists/* # Set work directory WORKDIR /app # Copy requirements and install dependencies COPY requirements.txt . RUN --mount=type=cache,target=/root/.cache/pip \ pip install --upgrade pip \ && pip install --user -r requirements.txt # Production stage FROM ${BASE_IMAGE} # Set labels LABEL maintainer="Delphi Consulting Group Inc." \ version="${VERSION}" \ build_date="${BUILD_DATE}" \ vcs_ref="${VCS_REF}" \ description="Delphi Consulting Group Database System" # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PYTHONPATH=/app \ PORT=8000 \ WORKERS=4 # Install runtime dependencies only RUN apt-get update \ && apt-get install -y --no-install-recommends \ bash \ curl \ sqlite3 \ tini \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean # Create non-root user RUN addgroup --system --gid 1001 delphi \ && adduser --system --uid 1001 --gid 1001 --no-create-home delphi # Set work directory WORKDIR /app # Copy Python packages from builder into system prefix so non-root user can access them COPY --from=builder /root/.local /usr/local # Copy application code COPY --chown=delphi:delphi . . # Copy and set up initialization script COPY scripts/init-container.sh /usr/local/bin/init-container.sh # Normalize line endings to avoid shebang issues and ensure executable RUN sed -i 's/\r$//' /usr/local/bin/init-container.sh && chmod +x /usr/local/bin/init-container.sh # Create necessary directories RUN mkdir -p /app/data /app/uploads /app/backups /app/exports /app/logs \ && chown -R delphi:delphi /app/data /app/uploads /app/backups /app/exports /app/logs # Create volume mount points VOLUME ["/app/data", "/app/uploads", "/app/backups"] # Switch to non-root user USER delphi # Expose port EXPOSE 8000 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 # Use tini as init system ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/init-container.sh"] # Start with gunicorn for production CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000", "--timeout", "120", "--keep-alive", "5"]