# Customer Portal - Bulletproof Production Dockerfile # Security-hardened, multi-stage build # ============================================================================= # Stage 1: Build dependencies # ============================================================================= FROM python:3.13-slim-bookworm AS builder WORKDIR /build # Install build-time dependencies (not in final image) RUN apt-get update && apt-get install -y --no-install-recommends \ libpq-dev \ gcc \ && rm -rf /var/lib/apt/lists/* # Create virtual environment for clean dependency isolation RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" COPY requirements.txt . RUN pip install --no-cache-dir --no-warn-script-location -r requirements.txt # ============================================================================= # Stage 2: Production image # ============================================================================= FROM python:3.13-slim-bookworm # OCI Labels LABEL org.opencontainers.image.title="Customer Portal" LABEL org.opencontainers.image.description="Customer portal for Kurs-Booking" LABEL org.opencontainers.image.vendor="webideas24" LABEL org.opencontainers.image.version="1.0.0" LABEL org.opencontainers.image.source="https://git.islandpferde-melanieworbs.de/webideas24/customer-portal" # Security: Install tini and minimal runtime dependencies only RUN apt-get update && apt-get install -y --no-install-recommends \ tini \ libpq5 \ curl \ ca-certificates \ postgresql-client \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ && rm -rf /root/.cache WORKDIR /app # Copy virtual environment from builder COPY --from=builder /opt/venv /opt/venv # Security: Create non-root user with no shell RUN groupadd -r -g 1000 portal && \ useradd -r -u 1000 -g portal -s /usr/sbin/nologin -d /home/portal portal && \ mkdir -p /home/portal && \ chown -R portal:portal /app /home/portal # Copy application and entrypoint COPY --chown=portal:portal customer_portal/ customer_portal/ COPY --chown=portal:portal entrypoint.sh /app/entrypoint.sh RUN chmod 755 /app/entrypoint.sh # Switch to non-root user USER portal # Environment ENV PATH="/opt/venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ FLASK_ENV=production \ PIP_NO_CACHE_DIR=1 EXPOSE 8000 STOPSIGNAL SIGTERM HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ CMD curl -fsS http://localhost:8000/health || exit 1 # Use tini as init, entrypoint handles migrations ENTRYPOINT ["/usr/bin/tini", "--", "/app/entrypoint.sh"]