Compare commits
73 Commits
feature/re
...
79b10e21d9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79b10e21d9 | ||
|
|
afd7183e31 | ||
|
|
4c09d583e7 | ||
|
|
24b78be310 | ||
|
|
a7bb756bc4 | ||
|
|
1de1ab0a23 | ||
|
|
a800d7f433 | ||
|
|
cd5960e426 | ||
|
|
ed1d18ce94 | ||
|
|
94c4e952fa | ||
|
|
17250b7615 | ||
|
|
b70c0bf466 | ||
|
|
a956c745ea | ||
|
|
062e71881d | ||
|
|
237e4583da | ||
|
|
ab62554216 | ||
|
|
dfa46aa4be | ||
|
|
4ebc169079 | ||
|
|
0eb0644d8c | ||
|
|
f953e52fd4 | ||
|
|
9a54cb4098 | ||
|
|
631c21bed5 | ||
|
|
3337ef143e | ||
|
|
222c37393f | ||
|
|
f574a90c6c | ||
|
|
6683ed1f15 | ||
|
|
2056fdb5ed | ||
|
|
2f03161423 | ||
|
|
75dc0b9a28 | ||
|
|
7b78b67ec8 | ||
|
|
5fa32903df | ||
|
|
00cd8aed90 | ||
|
|
066ce4a5c1 | ||
|
|
3d241f5269 | ||
|
|
0770278974 | ||
|
|
e795687d04 | ||
|
|
12aba3df78 | ||
|
|
ad5c43087a | ||
|
|
a5324456ec | ||
|
|
293096ca13 | ||
|
|
b9fbbe12ae | ||
|
|
97adff7c7e | ||
|
|
a5613d5d22 | ||
|
|
e49a077abd | ||
|
|
539011e3df | ||
|
|
61f6462cd8 | ||
|
|
8a0951a956 | ||
|
|
3537ba31ba | ||
|
|
ab93982675 | ||
|
|
66e7985eb4 | ||
|
|
a26e948fde | ||
|
|
cec835e77b | ||
|
|
b16e45cdd6 | ||
|
|
a0a3258f3a | ||
|
|
38effdb6a9 | ||
|
|
d24a419aa0 | ||
|
|
b33b0da6ab | ||
|
|
bd89a7b680 | ||
|
|
c1f4f2a71a | ||
|
|
0347338a30 | ||
|
|
72c127f0c2 | ||
|
|
ec7f90b0de | ||
|
|
69deeea1a3 | ||
|
|
10aed88c23 | ||
|
|
d728bd30cc | ||
|
|
703c2c9bc7 | ||
|
|
fbd2f9845c | ||
|
|
c8f69caf06 | ||
|
|
9b661d635e | ||
|
|
c4a478c20d | ||
|
|
2e96c28840 | ||
|
|
ed66aff5c0 | ||
|
|
3091de3e79 |
200
.woodpecker.yml
200
.woodpecker.yml
@@ -1,6 +1,7 @@
|
|||||||
# Woodpecker CI/CD Pipeline - Peikarband Landing
|
# Woodpecker CI/CD Pipeline - Peikarband Landing
|
||||||
# Smart pipeline with base image management
|
# Smart pipeline with base image management
|
||||||
|
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
- &base_image 'hub.peikarband.ir/peikarband/landing:base'
|
- &base_image 'hub.peikarband.ir/peikarband/landing:base'
|
||||||
- &app_image 'hub.peikarband.ir/peikarband/landing'
|
- &app_image 'hub.peikarband.ir/peikarband/landing'
|
||||||
@@ -8,7 +9,7 @@ variables:
|
|||||||
when:
|
when:
|
||||||
- event: [push, pull_request, tag, manual]
|
- event: [push, pull_request, tag, manual]
|
||||||
|
|
||||||
pipeline:
|
steps:
|
||||||
# ============================================
|
# ============================================
|
||||||
# Ensure Base Image Exists
|
# Ensure Base Image Exists
|
||||||
# ============================================
|
# ============================================
|
||||||
@@ -18,18 +19,18 @@ pipeline:
|
|||||||
settings:
|
settings:
|
||||||
registry: hub.peikarband.ir
|
registry: hub.peikarband.ir
|
||||||
repo: *app_image
|
repo: *app_image
|
||||||
username:
|
# username:
|
||||||
from_secret: HARBOR_USERNAME
|
# from_secret: HARBOR_USERNAME
|
||||||
password:
|
# password:
|
||||||
from_secret: HARBOR_PASSWORD
|
# from_secret: HARBOR_PASSWORD
|
||||||
|
username: admin
|
||||||
|
password: 5459ed7590d37656410fae38bdf59eb7ee33b68cd4c
|
||||||
dockerfile: docker/Dockerfile.base
|
dockerfile: docker/Dockerfile.base
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
- base
|
- base
|
||||||
- base-python3.11-node20
|
|
||||||
|
|
||||||
build_args:
|
build_args:
|
||||||
- PYTHON_VERSION=3.11
|
- PYTHON_VERSION=3.11
|
||||||
@@ -43,15 +44,14 @@ pipeline:
|
|||||||
- org.opencontainers.image.title=Peikarband Base
|
- org.opencontainers.image.title=Peikarband Base
|
||||||
- org.opencontainers.image.description=Base image with Python, Node.js, bun, and build tools
|
- org.opencontainers.image.description=Base image with Python, Node.js, bun, and build tools
|
||||||
|
|
||||||
pull: true
|
cache: inline
|
||||||
provenance: false
|
provenance: true
|
||||||
sbom: false
|
sbom: true
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
event: [push, tag, manual]
|
event: [push, tag, manual]
|
||||||
branch: [main, develop, feature/restructure-project]
|
branch: [main, develop]
|
||||||
# Only rebuild base if its definition changed
|
# Only rebuild base if its definition changed
|
||||||
path:
|
path:
|
||||||
include:
|
include:
|
||||||
@@ -65,6 +65,8 @@ pipeline:
|
|||||||
build-and-push-app:
|
build-and-push-app:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
settings:
|
settings:
|
||||||
|
debug: true
|
||||||
|
log-level: debug
|
||||||
registry: hub.peikarband.ir
|
registry: hub.peikarband.ir
|
||||||
repo: *app_image
|
repo: *app_image
|
||||||
username:
|
username:
|
||||||
@@ -95,102 +97,110 @@ pipeline:
|
|||||||
- org.opencontainers.image.title=Peikarband Landing
|
- org.opencontainers.image.title=Peikarband Landing
|
||||||
- org.opencontainers.image.description=Peikarband hosting platform landing page
|
- org.opencontainers.image.description=Peikarband hosting platform landing page
|
||||||
|
|
||||||
pull: true
|
# cache: inline
|
||||||
provenance: false
|
# provenance: true
|
||||||
sbom: false
|
# sbom: true
|
||||||
push: true
|
push: true
|
||||||
|
# Cache configuration - using inline cache instead of registry cache
|
||||||
|
# cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:cache
|
||||||
|
# cache_to: type=registry,ref=hub.peikarband.ir/peikarband/landing:cache,mode=max
|
||||||
|
|
||||||
when:
|
when:
|
||||||
event: [push, tag]
|
event: [push, tag]
|
||||||
branch: [main, develop, feature/restructure-project]
|
branch: [main, develop,]
|
||||||
|
|
||||||
# ============================================
|
# # ============================================
|
||||||
# Verify Images
|
# # Verify Images
|
||||||
# ============================================
|
# # ============================================
|
||||||
|
|
||||||
verify-images:
|
# verify-images:
|
||||||
image: alpine:latest
|
# image: alpine:latest
|
||||||
commands:
|
# commands:
|
||||||
- apk add --no-cache curl
|
# - apk add --no-cache curl
|
||||||
- |
|
# - |
|
||||||
echo "════════════════════════════════════════"
|
# echo "════════════════════════════════════════"
|
||||||
echo " 🔍 Verifying Images in Registry"
|
# echo " 🔍 Verifying Images in Registry"
|
||||||
echo "════════════════════════════════════════"
|
# echo "════════════════════════════════════════"
|
||||||
echo ""
|
# echo ""
|
||||||
|
|
||||||
# Check base image
|
# # Check base image
|
||||||
echo "Checking base image..."
|
# echo "Checking base image..."
|
||||||
if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \
|
# if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \
|
||||||
"https://hub.peikarband.ir/v2/peikarband/landing/manifests/base" > /dev/null 2>&1; then
|
# "https://hub.peikarband.ir/v2/peikarband/landing/manifests/base" > /dev/null 2>&1; then
|
||||||
echo "✅ Base image: hub.peikarband.ir/peikarband/landing:base"
|
# echo "✅ Base image: hub.peikarband.ir/peikarband/landing:base"
|
||||||
else
|
# else
|
||||||
echo "⚠️ Base image not found (this is OK if first build)"
|
# echo "⚠️ Base image not found (this is OK if first build)"
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
echo ""
|
# echo ""
|
||||||
|
|
||||||
# Check app image
|
# # Check app image
|
||||||
echo "Checking app image..."
|
# echo "Checking app image..."
|
||||||
TAG="${CI_COMMIT_SHA:0:8}"
|
# TAG="${CI_COMMIT_SHA:0:8}"
|
||||||
if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \
|
# if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \
|
||||||
"https://hub.peikarband.ir/v2/peikarband/landing/manifests/$TAG" > /dev/null 2>&1; then
|
# "https://hub.peikarband.ir/v2/peikarband/landing/manifests/$TAG" > /dev/null 2>&1; then
|
||||||
echo "✅ App image: hub.peikarband.ir/peikarband/landing:$TAG"
|
# echo "✅ App image: hub.peikarband.ir/peikarband/landing:$TAG"
|
||||||
echo ""
|
# echo ""
|
||||||
echo "Available tags:"
|
# echo "Available tags:"
|
||||||
echo " • latest"
|
# echo " • latest"
|
||||||
echo " • ${CI_COMMIT_SHA:0:8}"
|
# echo " • ${CI_COMMIT_SHA:0:8}"
|
||||||
echo " • ${CI_COMMIT_BRANCH}"
|
# echo " • ${CI_COMMIT_BRANCH}"
|
||||||
echo ""
|
# echo ""
|
||||||
echo "════════════════════════════════════════"
|
# echo "════════════════════════════════════════"
|
||||||
else
|
# else
|
||||||
echo "❌ Failed to verify app image"
|
# echo "❌ Failed to verify app image"
|
||||||
exit 1
|
# exit 1
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
secrets: [HARBOR_USERNAME, HARBOR_PASSWORD]
|
# environment:
|
||||||
when:
|
# HARBOR_USERNAME:
|
||||||
event: [push, tag]
|
# from_secret: HARBOR_USERNAME
|
||||||
branch: [main, develop, feature/restructure-project]
|
# HARBOR_PASSWORD:
|
||||||
|
# from_secret: HARBOR_PASSWORD
|
||||||
|
|
||||||
|
# when:
|
||||||
|
# event: [push, tag]
|
||||||
|
# branch: [main, develop]
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Notifications
|
# Notifications
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
notify-success:
|
# notify-success:
|
||||||
image: alpine:latest
|
# image: alpine:latest
|
||||||
commands:
|
# commands:
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
- echo " 🎉 Pipeline Completed Successfully!"
|
# - echo " 🎉 Pipeline Completed Successfully!"
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "Branch:" "${CI_COMMIT_BRANCH}"
|
# - echo "Branch:" "${CI_COMMIT_BRANCH}"
|
||||||
- echo "Commit:" "${CI_COMMIT_SHA:0:8}"
|
# - echo "Commit:" "${CI_COMMIT_SHA:0:8}"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "Images:"
|
# - echo "Images:"
|
||||||
- echo " • Base:" "hub.peikarband.ir/peikarband/landing:base"
|
# - echo " • Base:" "hub.peikarband.ir/peikarband/landing:base"
|
||||||
- echo " • App:" "hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}"
|
# - echo " • App:" "hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "Deploy with:"
|
# - echo "Deploy with:"
|
||||||
- echo " kubectl set image deployment/peikarband-landing \\"
|
# - echo " kubectl set image deployment/peikarband-landing \\"
|
||||||
- echo " peikarband-landing=hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}"
|
# - echo " peikarband-landing=hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
when:
|
# when:
|
||||||
event: [push, tag]
|
# event: [push, tag]
|
||||||
status: success
|
# status: success
|
||||||
|
|
||||||
notify-failure:
|
# notify-failure:
|
||||||
image: alpine:latest
|
# image: alpine:latest
|
||||||
commands:
|
# commands:
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
- echo " ❌ Pipeline Failed!"
|
# - echo " ❌ Pipeline Failed!"
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "Branch:" "${CI_COMMIT_BRANCH}"
|
# - echo "Branch:" "${CI_COMMIT_BRANCH}"
|
||||||
- echo "Commit:" "${CI_COMMIT_SHA:0:8}"
|
# - echo "Commit:" "${CI_COMMIT_SHA:0:8}"
|
||||||
- echo ""
|
# - echo ""
|
||||||
- echo "Please check the logs above"
|
# - echo "Please check the logs above"
|
||||||
- echo "════════════════════════════════════════"
|
# - echo "════════════════════════════════════════"
|
||||||
when:
|
# when:
|
||||||
event: [push, tag]
|
# event: [push, tag]
|
||||||
status: failure
|
# status: failure
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Optimized multi-stage build using base image
|
# Optimized multi-stage build using base image
|
||||||
|
|
||||||
# Build arguments
|
# Build arguments
|
||||||
ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest
|
ARG BASE_IMAGE=hub.peikarband.ir/peikarband/landing:base
|
||||||
ARG VERSION=latest
|
ARG VERSION=latest
|
||||||
ARG BUILD_DATE
|
ARG BUILD_DATE
|
||||||
|
|
||||||
@@ -46,32 +46,67 @@ RUN --mount=type=cache,target=/root/.cache/pip \
|
|||||||
# Frontend Build (Reflex)
|
# Frontend Build (Reflex)
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
# Copy source code
|
# Copy source code to /build/peikarband/ to preserve package structure
|
||||||
COPY peikarband/ .
|
# This ensures peikarband.peikarband module can be found by Reflex
|
||||||
|
COPY peikarband/ /build/peikarband/
|
||||||
|
|
||||||
# Initialize Reflex and build frontend
|
# Set PYTHONPATH to include /build (for peikarband package) and /build/peikarband (for src imports)
|
||||||
RUN reflex init --loglevel debug || true && \
|
# This allows both peikarband.peikarband and src.* imports to work
|
||||||
|
ENV PYTHONPATH=/build:/build/peikarband
|
||||||
|
|
||||||
|
# Verify that peikarband.peikarband can be imported before running reflex
|
||||||
|
# This helps catch import errors early
|
||||||
|
RUN cd /build && \
|
||||||
|
python3 -c "from peikarband.peikarband import app; print('✅ peikarband.peikarband.app imported successfully')" && \
|
||||||
|
echo "Import test passed"
|
||||||
|
|
||||||
|
# Initialize Reflex and build frontend from peikarband directory
|
||||||
|
# Reflex needs to run from the directory containing rxconfig.py
|
||||||
|
RUN cd /build/peikarband && \
|
||||||
|
reflex init --loglevel debug || true && \
|
||||||
reflex export --frontend-only --no-zip --loglevel debug || echo "Export completed with warnings"
|
reflex export --frontend-only --no-zip --loglevel debug || echo "Export completed with warnings"
|
||||||
|
|
||||||
# Build frontend with npm (fallback if reflex export fails)
|
# Install npm dependencies if .web directory exists
|
||||||
WORKDIR /build/.web
|
# Note: reflex export already builds the frontend, we just need to install deps
|
||||||
|
RUN if [ -d "/build/peikarband/.web" ] && [ -f "/build/peikarband/.web/package.json" ]; then \
|
||||||
# Configure npm for better reliability
|
echo "Found .web directory with package.json, installing dependencies..." && \
|
||||||
RUN npm config set fetch-retry-mintimeout 20000 && \
|
cd /build/peikarband/.web && \
|
||||||
|
# Remove any existing .npmrc that might override registry
|
||||||
|
rm -f .npmrc && \
|
||||||
|
# Set npm registry to official registry
|
||||||
|
npm config set registry https://registry.npmjs.org/ && \
|
||||||
|
npm config set fetch-retry-mintimeout 20000 && \
|
||||||
npm config set fetch-retry-maxtimeout 120000 && \
|
npm config set fetch-retry-maxtimeout 120000 && \
|
||||||
npm config set fetch-retries 5 && \
|
npm config set fetch-retries 5 && \
|
||||||
npm config set fetch-timeout 300000
|
npm config set fetch-timeout 300000 && \
|
||||||
|
# Verify registry is set correctly
|
||||||
# Install and build
|
echo "Using npm registry: $(npm config get registry)" && \
|
||||||
RUN --mount=type=cache,target=/root/.npm \
|
# Install dependencies (reflex export already built the frontend)
|
||||||
npm ci --prefer-offline --no-audit --loglevel verbose && \
|
if [ -f "package-lock.json" ]; then \
|
||||||
npm run build
|
npm ci --prefer-offline --no-audit --loglevel verbose || \
|
||||||
|
(echo "npm ci failed, retrying with npm install..." && npm install --prefer-offline --no-audit --loglevel verbose); \
|
||||||
|
else \
|
||||||
|
echo "package-lock.json not found, using npm install..." && \
|
||||||
|
npm install --prefer-offline --no-audit --loglevel verbose; \
|
||||||
|
fi && \
|
||||||
|
echo "Dependencies installed successfully"; \
|
||||||
|
else \
|
||||||
|
echo "Warning: .web directory or package.json not found, skipping npm install"; \
|
||||||
|
fi
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Stage 2: Runtime (using base image for Node.js)
|
# Stage 2: Runtime (using base image for Node.js)
|
||||||
# ============================================
|
# ============================================
|
||||||
FROM ${BASE_IMAGE} AS runtime
|
FROM ${BASE_IMAGE} AS runtime
|
||||||
|
|
||||||
|
# Re-declare build arguments for this stage
|
||||||
|
ARG BASE_IMAGE=hub.peikarband.ir/peikarband/landing:base
|
||||||
|
ARG VERSION=latest
|
||||||
|
ARG BUILD_DATE
|
||||||
|
ARG GIT_COMMIT
|
||||||
|
ARG GIT_BRANCH
|
||||||
|
ARG BUILD_NUMBER
|
||||||
|
|
||||||
LABEL org.opencontainers.image.title="Peikarband Landing"
|
LABEL org.opencontainers.image.title="Peikarband Landing"
|
||||||
LABEL org.opencontainers.image.description="Peikarband hosting platform landing page"
|
LABEL org.opencontainers.image.description="Peikarband hosting platform landing page"
|
||||||
LABEL org.opencontainers.image.vendor="Peikarband"
|
LABEL org.opencontainers.image.vendor="Peikarband"
|
||||||
@@ -84,6 +119,10 @@ RUN groupadd -r peikarband && \
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Note: We keep WORKDIR=/app (not /app/peikarband) to avoid Python importing
|
||||||
|
# /app/peikarband/peikarband/ as the peikarband package
|
||||||
|
# The entrypoint script will cd to /app/peikarband before running reflex
|
||||||
|
|
||||||
# Base image already has everything we need:
|
# Base image already has everything we need:
|
||||||
# - Python 3.11
|
# - Python 3.11
|
||||||
# - Node.js 20
|
# - Node.js 20
|
||||||
@@ -95,8 +134,13 @@ WORKDIR /app
|
|||||||
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
||||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||||
|
|
||||||
# Copy application code
|
# Copy application code to /app/peikarband/ to create peikarband.peikarband structure
|
||||||
COPY --from=builder --chown=peikarband:peikarband /build /app
|
# With app_name="peikarband", Reflex expects to find peikarband.peikarband module
|
||||||
|
COPY --from=builder --chown=peikarband:peikarband /build/peikarband /app/peikarband
|
||||||
|
|
||||||
|
# Copy entrypoint script
|
||||||
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
# Create necessary directories
|
# Create necessary directories
|
||||||
RUN mkdir -p /app/data /app/logs /app/uploaded_files && \
|
RUN mkdir -p /app/data /app/logs /app/uploaded_files && \
|
||||||
@@ -107,11 +151,16 @@ RUN chmod -R 755 /app && \
|
|||||||
chmod -R 777 /app/data /app/logs /app/uploaded_files
|
chmod -R 777 /app/data /app/logs /app/uploaded_files
|
||||||
|
|
||||||
# Environment variables
|
# Environment variables
|
||||||
|
# PYTHONPATH includes both /app and /app/peikarband
|
||||||
|
# - /app: allows importing peikarband from /app/peikarband/
|
||||||
|
# - /app/peikarband: allows importing src from /app/peikarband/src/
|
||||||
|
# This makes both peikarband.peikarband and src.* imports work correctly
|
||||||
|
# REFLEX_DIR points to the directory containing rxconfig.py
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
PYTHONDONTWRITEBYTECODE=1 \
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONPATH=/app \
|
PYTHONPATH=/app:/app/peikarband \
|
||||||
PATH="/app/.venv/bin:$PATH" \
|
PATH="/app/.venv/bin:$PATH" \
|
||||||
REFLEX_DIR=/app \
|
REFLEX_DIR=/app/peikarband \
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
@@ -125,18 +174,17 @@ USER peikarband
|
|||||||
EXPOSE 3000 8000
|
EXPOSE 3000 8000
|
||||||
|
|
||||||
# Use tini as init system
|
# Use tini as init system
|
||||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
|
||||||
|
|
||||||
# Start application
|
# Start application
|
||||||
CMD ["reflex", "run", "--env", "prod", "--loglevel", "info"]
|
# entrypoint.sh will cd to /app/peikarband and run reflex
|
||||||
|
# PYTHONPATH=/app:/app/peikarband allows Python to find both peikarband and peikarband.peikarband
|
||||||
|
CMD ["run", "--env", "prod", "--loglevel", "info", "--frontend-port", "3000", "--backend-port", "8000"]
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# Build Information
|
# Build Information
|
||||||
# ============================================
|
# ============================================
|
||||||
ARG GIT_COMMIT
|
# ARG declarations are already done above in runtime stage
|
||||||
ARG GIT_BRANCH
|
|
||||||
ARG BUILD_NUMBER
|
|
||||||
|
|
||||||
LABEL git.commit="${GIT_COMMIT}"
|
LABEL git.commit="${GIT_COMMIT}"
|
||||||
LABEL git.branch="${GIT_BRANCH}"
|
LABEL git.branch="${GIT_BRANCH}"
|
||||||
LABEL build.number="${BUILD_NUMBER}"
|
LABEL build.number="${BUILD_NUMBER}"
|
||||||
|
|||||||
51
docker/Dockerfile copy
Normal file
51
docker/Dockerfile copy
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# استفاده از ایمیج پایهای که قبلاً Push کردید
|
||||||
|
ARG BASE_IMAGE=hub.peikarband.ir/peikarband/landing:base
|
||||||
|
FROM ${BASE_IMAGE} AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# ۱. کپی کردن فایلهای نیازمندی (برای استفاده از Cache)
|
||||||
|
COPY peikarband/requirements.txt .
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# ۲. کپی کردن کل کدها
|
||||||
|
# مهم: ساختار فولدر باید با app_name در rxconfig.py یکی باشد
|
||||||
|
COPY peikarband/ .
|
||||||
|
|
||||||
|
# ۳. تنظیم PYTHONPATH برای حل مشکل ModuleNotFoundError
|
||||||
|
ENV PYTHONPATH=/app
|
||||||
|
|
||||||
|
# ۴. اجرای Reflex Export
|
||||||
|
# این دستور خودش فرانتتند را بیلد میکند و نیازی به npm run build دستی نیست
|
||||||
|
RUN reflex init --loglevel debug
|
||||||
|
RUN reflex export --frontend-only --no-zip --loglevel debug
|
||||||
|
|
||||||
|
# ================= Stage 2: Runtime =================
|
||||||
|
FROM ${BASE_IMAGE} AS runtime
|
||||||
|
|
||||||
|
# ایجاد یوزر غیر ریشه برای امنیت
|
||||||
|
RUN groupadd -r peikarband && useradd -r -g peikarband -u 1000 -m peikarband
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# کپی کردن کتابخانههای نصب شده از مرحله قبل
|
||||||
|
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
||||||
|
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||||
|
|
||||||
|
# کپی کردن کد اپلیکیشن و فایلهای بیلد شده فرانتتند
|
||||||
|
COPY --from=builder --chown=peikarband:peikarband /app /app
|
||||||
|
|
||||||
|
# ایجاد پوشههای مورد نیاز
|
||||||
|
RUN mkdir -p data logs uploaded_files && \
|
||||||
|
chown -R peikarband:peikarband /app && \
|
||||||
|
chmod -R 755 /app
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONPATH=/app \
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
|
USER peikarband
|
||||||
|
EXPOSE 3000 8000
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
|
CMD ["reflex", "run", "--env", "prod"]
|
||||||
27
docker/Dockerfile copy.base
Normal file
27
docker/Dockerfile copy.base
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Peikarband Base Image
|
||||||
|
ARG PYTHON_VERSION=3.11
|
||||||
|
FROM python:${PYTHON_VERSION}-slim
|
||||||
|
|
||||||
|
# نصب ابزارهای سیستم و پاکسازی برای کاهش حجم
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc g++ make curl gnupg ca-certificates unzip git tini \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# نصب Node.js 20
|
||||||
|
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||||
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# نصب Bun با مکانیزم Retry برای پایداری در شبکه
|
||||||
|
RUN set -ex && \
|
||||||
|
for i in 1 2 3 4 5; do \
|
||||||
|
curl -fsSL https://bun.sh/install | bash && break || \
|
||||||
|
(echo "Attempt $i failed, retrying in 5 seconds..." && sleep 5); \
|
||||||
|
done
|
||||||
|
ENV PATH="/root/.bun/bin:${PATH}"
|
||||||
|
|
||||||
|
# آپدیت ابزارهای پایتون
|
||||||
|
RUN pip install --no-cache-dir --upgrade pip setuptools wheel
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
CMD ["/bin/bash"]
|
||||||
9
docker/entrypoint.sh
Normal file
9
docker/entrypoint.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Change to the directory containing rxconfig.py
|
||||||
|
cd /app/peikarband
|
||||||
|
|
||||||
|
# Run reflex with all passed arguments
|
||||||
|
exec reflex "$@"
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ replicaCount: 1
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
tag: "latest"
|
||||||
|
|
||||||
# Auto-create registry secret
|
# Auto-create registry secret
|
||||||
registrySecret:
|
registrySecret:
|
||||||
|
|||||||
6
peikarband/__init__.py
Normal file
6
peikarband/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
"""Peikarband Landing Application Package.
|
||||||
|
|
||||||
|
This package exports the Reflex app instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = []
|
||||||
10
peikarband/app.py
Normal file
10
peikarband/app.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
"""Peikarband Landing Application Entry Point.
|
||||||
|
|
||||||
|
This file exports the Reflex app instance for the landing page.
|
||||||
|
Reflex will look for 'app' in the root module when app_name matches the root directory.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from src.presentation.web.pages.landing.index import app
|
||||||
|
|
||||||
|
__all__ = ["app"]
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
"""Reflex configuration file.
|
|
||||||
|
|
||||||
This file configures the Reflex application settings.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import reflex as rx
|
|
||||||
|
|
||||||
# Environment-aware configuration
|
|
||||||
API_URL = os.getenv("API_URL", "http://localhost:8000")
|
|
||||||
FRONTEND_PORT = int(os.getenv("FRONTEND_PORT", "3000"))
|
|
||||||
BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
|
|
||||||
DB_URL = os.getenv("DATABASE_URL", "sqlite:///reflex.db")
|
|
||||||
|
|
||||||
config = rx.Config(
|
|
||||||
app_name="peikarband",
|
|
||||||
api_url=API_URL,
|
|
||||||
frontend_port=FRONTEND_PORT,
|
|
||||||
backend_port=BACKEND_PORT,
|
|
||||||
db_url=DB_URL,
|
|
||||||
disable_plugins=["reflex.plugins.sitemap.SitemapPlugin"],
|
|
||||||
stylesheets=[
|
|
||||||
"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap",
|
|
||||||
"https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
8
peikarband/landing/__init__.py
Normal file
8
peikarband/landing/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
"""Landing page app module.
|
||||||
|
|
||||||
|
Reflex expects to find 'app' in peikarband.landing when app_name='landing'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from peikarband.app import app
|
||||||
|
|
||||||
|
__all__ = ["app"]
|
||||||
@@ -13,7 +13,7 @@ BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
|
|||||||
DB_URL = os.getenv("DATABASE_URL", "sqlite:////app/data/reflex.db")
|
DB_URL = os.getenv("DATABASE_URL", "sqlite:////app/data/reflex.db")
|
||||||
|
|
||||||
config = rx.Config(
|
config = rx.Config(
|
||||||
app_name="peikarband",
|
app_name="landing",
|
||||||
api_url=API_URL,
|
api_url=API_URL,
|
||||||
frontend_port=FRONTEND_PORT,
|
frontend_port=FRONTEND_PORT,
|
||||||
backend_port=BACKEND_PORT,
|
backend_port=BACKEND_PORT,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
"""Peikarband Landing Application.
|
||||||
|
|
||||||
|
This module exports the Reflex app instance for the landing page.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Import the app from the landing page module using relative import
|
||||||
|
from .presentation.web.pages.landing.index import app
|
||||||
|
|
||||||
|
__all__ = ["app"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user