diff --git a/.github/workflows/image-push.yml b/.github/workflows/image-push.yml index 8f19003..9fa26fa 100644 --- a/.github/workflows/image-push.yml +++ b/.github/workflows/image-push.yml @@ -15,6 +15,8 @@ jobs: permissions: contents: read packages: write + id-token: write + attestations: write steps: - name: Checkout code @@ -22,6 +24,9 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + network=host - name: Log in to Container Registry uses: docker/login-action@v3 @@ -36,16 +41,15 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=ref,event=branch - type=ref,event=pr type=raw,value=latest,enable={{is_default_branch}} - type=sha,prefix={{branch}}- + type=sha - name: Build and push Docker image + id: build uses: docker/build-push-action@v5 with: context: . - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 # Single platform for faster builds push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} @@ -54,6 +58,7 @@ jobs: - name: Generate artifact attestation uses: actions/attest-build-provenance@v1 + if: github.event_name != 'pull_request' with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.build.outputs.digest }} diff --git a/Dockerfile b/Dockerfile index 7ba4fd2..f946bc9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,53 @@ -# Use Python 3.13 slim image -FROM python:3.13-slim +# Multi-stage build for optimization +FROM python:3.13-slim as builder -# Set environment variables -ENV PYTHONDONTWRITEBYTECODE=1 \ - PYTHONUNBUFFERED=1 \ - PIP_NO_CACHE_DIR=1 \ +# Set environment variables for build stage +ENV PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 -# Set work directory -WORKDIR /app - -# Install system dependencies +# Install build dependencies RUN apt-get update \ && apt-get install -y --no-install-recommends \ - postgresql-client \ build-essential \ libpq-dev \ && rm -rf /var/lib/apt/lists/* # Install Python dependencies COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --user -r requirements.txt -# Copy project -COPY . . +# Production stage +FROM python:3.13-slim -# Create non-root user -RUN adduser --disabled-password --gecos '' appuser \ - && chown -R appuser:appuser /app +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PATH=/home/appuser/.local/bin:$PATH + +# Install runtime dependencies only +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + postgresql-client \ + libpq5 \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get purge -y --auto-remove + +# Create non-root user first +RUN adduser --disabled-password --gecos '' appuser + +# Copy Python packages from builder stage +COPY --from=builder /root/.local /home/appuser/.local + +# Set work directory and ownership +WORKDIR /app +RUN chown appuser:appuser /app + +# Switch to non-root user USER appuser +# Copy project files +COPY --chown=appuser:appuser . . + # Collect static files RUN python manage.py collectstatic --noinput