# React.js Optimized Dockerfile (No Nginx) # Auto-generated for {{ app_name }} # Node.js Version: {{ node_version }} # Package Manager: {{ package_manager }} # ============================================================================ # Build arguments # ============================================================================ ARG NODE_VERSION={{ node_version }} ARG PACKAGE_MANAGER={{ package_manager }} ARG BUILD_COMMAND={{ build_command }} ARG APP_PORT={{ framework_settings_port }} # ============================================================================ # Base stage # ============================================================================ FROM gitlab.forlife.one:5050/share/node:${NODE_VERSION}-alpine AS base # Install dependencies RUN apk add --no-cache \ libc6-compat \ python3 \ make \ g++ curl WORKDIR /app # ============================================================================ # Dependencies stage # ============================================================================ FROM base AS deps # Copy package files COPY package*.json yarn.lock* pnpm-lock.yaml* ./ # Install dependencies #RUN yarn install RUN {{ package_manager }} install # ============================================================================ # Builder stage # ============================================================================ FROM base AS builder # Copy dependencies COPY --from=deps /app/node_modules ./node_modules # Copy source code COPY . . # Build arguments for runtime configuration ARG GIT_COMMIT=unknown ARG BUILD_DATE=unknown ARG REACT_APP_VERSION={{ docker_image_tag }} # Set build environment ENV NODE_ENV=production ENV GENERATE_SOURCEMAP=false ENV REACT_APP_VERSION=${REACT_APP_VERSION} ENV REACT_APP_BUILD_DATE=${BUILD_DATE} ENV REACT_APP_GIT_COMMIT=${GIT_COMMIT} # Create build info file RUN echo '{"version":"{{ docker_image_tag }}","commit":"'${GIT_COMMIT}'","buildDate":"'${BUILD_DATE}'","framework":"reactjs","nodeVersion":"{{ node_version }}"}' > public/build-info.json # Require BuildKit enabled # Mount secret nếu tồn tại, copy vào thư mục app RUN --mount=type=secret,id=env,target=/run/secrets/env \ cp /run/secrets/env .env || echo ".env not found" # ============================================================================ # Build the application # ============================================================================ RUN \ if [ -f yarn.lock ]; then \ yarn build; \ elif [ -f package-lock.json ]; then \ npm run build; \ elif [ -f pnpm-lock.yaml ]; then \ pnpm build; \ else \ npm run build; \ fi # ============================================================================ # Production stage with serve # ============================================================================ FROM node:${NODE_VERSION}-alpine AS production # Install curl for health checks RUN apk add --no-cache curl WORKDIR /app # Install serve globally for serving static files RUN npm install -g serve # Copy built React app COPY --from=builder /app/build ./build # Create package.json for serving RUN echo '{ \ "name": "{{ app_name }}-server", \ "version": "{{ docker_image_tag }}", \ "scripts": { \ "start": "serve -s build -l 3000" \ }, \ "dependencies": { \ "serve": "latest" \ } \ }' > package.json # Create serve.json configuration RUN echo '{ \ "public": "build", \ "rewrites": [ \ { "source": "**", "destination": "/index.html" } \ ], \ "headers": [ \ { \ "source": "**/*.@(jpg|jpeg|gif|png|svg|ico|css|js)", \ "headers": [ \ { \ "key": "Cache-Control", \ "value": "public, max-age=31536000, immutable" \ } \ ] \ }, \ { \ "source": "**", \ "headers": [ \ { \ "key": "X-Content-Type-Options", \ "value": "nosniff" \ }, \ { \ "key": "X-Frame-Options", \ "value": "DENY" \ }, \ { \ "key": "X-XSS-Protection", \ "value": "1; mode=block" \ } \ ] \ } \ ] \ }' > serve.json # Create health check endpoint RUN mkdir -p build && echo 'healthy' > build/health.txt # Create health check script RUN echo '#!/bin/sh\n\ status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:${APP_PORT}/health)\n\ if [ "$status" -eq 200 ] || [ "$status" -eq 404 ]; then exit 0; fi\n\ \n\ status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:${APP_PORT}/)\n\ if [ "$status" -eq 200 ] || [ "$status" -eq 404 ]; then exit 0; fi\n\ \n\ exit 1' > /health-check.sh && \ chmod +x /health-check.sh # Create non-root user RUN addgroup --system --gid 1001 reactapp && \ adduser --system --uid 1001 reactapp # Set proper permissions RUN chown -R reactapp:reactapp /app # Switch to non-root user USER reactapp # Expose port EXPOSE 3000 # Set environment variables ENV NODE_ENV=production ENV PORT=3000 ENV APP_PORT=3000 ENV NODE_OPTIONS="--max-old-space-size={{ MEMORY_LIMIT_MB }}" # Health check #HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 CMD /health-check.sh # Start the application #CMD ["npm", "start"] #CMD [ "serve", "-s", "build" ] CMD {{ RUN_CMD }}