From a8c7d3e73e398d68b2f1085bd6eb3910b43a8e3d Mon Sep 17 00:00:00 2001 From: Denis Shatskiy Date: Fri, 8 Aug 2025 08:47:59 +0700 Subject: [PATCH] refactor: Update Dockerfile to use glibc-based images for frontend and backend builds, and implement a minimal distroless runtime for improved security and efficiency. Enhance CI workflow with cleanup of old Docker images. --- .gitea/workflows/docker-publish-fast.yml | 27 +++++++++++- Dockerfile.fast | 54 +++++++++--------------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/.gitea/workflows/docker-publish-fast.yml b/.gitea/workflows/docker-publish-fast.yml index 3389c34..4987fc1 100644 --- a/.gitea/workflows/docker-publish-fast.yml +++ b/.gitea/workflows/docker-publish-fast.yml @@ -50,4 +50,29 @@ jobs: org.opencontainers.image.created=${{ gitea.event.head_commit.timestamp }} build-args: | BUILDKIT_INLINE_CACHE=1 - provenance: false \ No newline at end of file + provenance: false + + - name: Cleanup old images + run: | + # Get list of all tabler-fast images, sorted by creation date (newest first) + IMAGES=$(curl -s -H "Authorization: Bearer ${{ secrets.ACTIONS_PAT }}" \ + "https://git.shts.su/api/v1/repos/${{ gitea.repository }}/tags?page=1&limit=100" | \ + jq -r '.[] | select(.name | startswith("tabler-fast-")) | .name' | \ + sort -r) + + # Keep only the 3 most recent images + KEEP_COUNT=3 + COUNT=0 + + echo "$IMAGES" | while read -r tag; do + if [ -n "$tag" ]; then + COUNT=$((COUNT + 1)) + if [ $COUNT -gt $KEEP_COUNT ]; then + echo "Deleting old image: $tag" + curl -X DELETE -H "Authorization: Bearer ${{ secrets.ACTIONS_PAT }}" \ + "https://git.shts.su/api/v1/repos/${{ gitea.repository }}/tags/$tag" + else + echo "Keeping image: $tag" + fi + fi + done \ No newline at end of file diff --git a/Dockerfile.fast b/Dockerfile.fast index 278de3a..f9cabeb 100644 --- a/Dockerfile.fast +++ b/Dockerfile.fast @@ -1,63 +1,47 @@ # syntax=docker/dockerfile:1.6 -# Stage 1: Build React frontend -FROM node:20-alpine AS frontend-builder + +# Stage 1: Build React frontend on glibc +FROM node:20-bookworm-slim AS frontend-builder WORKDIR /app/frontend -# Install build dependencies for native modules -RUN apk add --no-cache python3 make g++ - -# Set npm config for better performance +ENV NODE_ENV=production RUN npm config set registry https://registry.npmjs.org/ \ - && npm config set fetch-timeout 300000 \ - && npm config set fetch-retry-mintimeout 20000 \ - && npm config set fetch-retry-maxtimeout 120000 + && npm config set fetch-timeout 300000 \ + && npm config set fetch-retry-mintimeout 20000 \ + && npm config set fetch-retry-maxtimeout 120000 -# Copy package files first for better caching COPY frontend/package*.json ./ - -# Install dependencies with cache (lockfile может отличаться после overrides/optional deps) RUN --mount=type=cache,target=/root/.npm npm install --no-audit --no-fund -# Copy source code (only what's needed for build) COPY frontend/src/ ./src/ COPY frontend/public/ ./public/ COPY frontend/index.html ./ COPY frontend/vite.config.js ./ COPY frontend/eslint.config.js ./ -# Build the application with optimized settings ENV ROLLUP_SKIP_NODEJS_NATIVE=1 ENV ROLLUP_NO_NATIVE=1 RUN npm run build -# Stage 2: Setup Node.js backend and serve everything -FROM node:20-alpine +# Stage 2: Install backend deps on glibc +FROM node:20-bookworm-slim AS backend-builder WORKDIR /app - -# Set npm config for better performance +ENV NODE_ENV=production RUN npm config set registry https://registry.npmjs.org/ \ - && npm config set fetch-timeout 300000 + && npm config set fetch-timeout 300000 -# Copy package files first for better caching COPY backend/package*.json ./ - -# Install production dependencies only with optimized flags RUN --mount=type=cache,target=/root/.npm npm ci --only=production --no-audit --no-fund -# Copy backend source code (only what's needed) -COPY backend/server.js ./ +# Stage 3: Minimal runtime (distroless) +FROM gcr.io/distroless/nodejs20-debian12:nonroot +WORKDIR /app -# Copy built frontend assets from the previous stage +# Copy runtime files +COPY --from=backend-builder /app/node_modules ./node_modules +COPY backend/server.js ./server.js COPY --from=frontend-builder /app/frontend/dist ./public -# Create non-root user for security -RUN addgroup -g 1001 -S nodejs -RUN adduser -S nodejs -u 1001 -RUN chown -R nodejs:nodejs /app -USER nodejs - -# The port the backend runs on EXPOSE 3001 - -# Start the server -CMD ["node", "server.js"] \ No newline at end of file +USER nonroot +CMD ["server.js"] \ No newline at end of file