refactor: reorganize project structure for better maintainability
- Move Docker files to build/docker/ - Move CI/CD configs to build/ci/ - Move deployment configs to deploy/ (helm, k8s, argocd) - Move config files to config/ - Move scripts to tools/ - Consolidate assets to assets/ (Reflex compatible) - Add data/ directory for local data (gitignored) - Update all path references in Makefile, Dockerfile, CI configs - Add comprehensive README files for build/ and deploy/ - Update project documentation Benefits: - Clear separation of concerns - Cleaner root directory - Better developer experience - Enterprise-grade structure - Improved maintainability
This commit is contained in:
81
build/README.md
Normal file
81
build/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Build Directory
|
||||
|
||||
این دایرکتوری شامل همه فایلهای مربوط به **build process** پروژه است.
|
||||
|
||||
## 📁 ساختار
|
||||
|
||||
```
|
||||
build/
|
||||
├── docker/ # Docker configurations
|
||||
│ ├── Dockerfile # Main application Dockerfile
|
||||
│ ├── Dockerfile.base # Base image reference
|
||||
│ ├── docker-compose.yml # Local development
|
||||
│ └── .dockerignore
|
||||
└── ci/ # CI/CD configurations
|
||||
└── woodpecker.yml # Woodpecker CI pipeline
|
||||
```
|
||||
|
||||
## 🐳 Docker
|
||||
|
||||
### Dockerfile
|
||||
Multi-stage Dockerfile برای بهینهسازی حجم image و امنیت:
|
||||
- **Stage 1 (Builder)**: Build و compile
|
||||
- **Stage 2 (Runtime)**: Image نهایی بدون build tools
|
||||
|
||||
**Build:**
|
||||
```bash
|
||||
make docker-build
|
||||
# یا
|
||||
docker build -f build/docker/Dockerfile -t peikarband/landing:latest .
|
||||
```
|
||||
|
||||
### Dockerfile.base
|
||||
فایل مرجع برای base image که در repo جداگانه build میشود:
|
||||
- Repo: `peikarband/base`
|
||||
- Registry: `hub.peikarband.ir/peikarband/base:latest`
|
||||
|
||||
### docker-compose.yml
|
||||
برای development محلی:
|
||||
```bash
|
||||
make docker-up
|
||||
# یا
|
||||
docker-compose -f build/docker/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
## 🔄 CI/CD
|
||||
|
||||
### woodpecker.yml
|
||||
Woodpecker CI pipeline configuration:
|
||||
- Build Docker image
|
||||
- Push به Harbor registry
|
||||
- Tag with commit SHA
|
||||
- Cache optimization
|
||||
|
||||
**تنظیمات مورد نیاز:**
|
||||
- `HARBOR_USERNAME`: Harbor registry username
|
||||
- `HARBOR_PASSWORD`: Harbor registry password
|
||||
|
||||
## 🎯 Best Practices
|
||||
|
||||
1. **Docker Images**
|
||||
- Multi-stage builds
|
||||
- Minimal runtime dependencies
|
||||
- Non-root user
|
||||
- Health checks
|
||||
|
||||
2. **CI/CD**
|
||||
- Cache layers
|
||||
- Automated testing
|
||||
- Semantic versioning
|
||||
- Registry push on main branch only
|
||||
|
||||
3. **Security**
|
||||
- Scan images for vulnerabilities
|
||||
- Sign images
|
||||
- Use specific versions (no `:latest` in production)
|
||||
|
||||
## 📚 مستندات بیشتر
|
||||
|
||||
- [Deployment Guide](../docs/deployment/kubernetes.md)
|
||||
- [Production Deployment](../docs/deployment/PRODUCTION_DEPLOYMENT.md)
|
||||
|
||||
46
build/ci/woodpecker.yml
Normal file
46
build/ci/woodpecker.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
pipeline:
|
||||
publish_landing:
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
# تنظیمات ریجیستری Harbor
|
||||
registry: hub.peikarband.ir
|
||||
repo: hub.peikarband.ir/peikarband/landing
|
||||
username:
|
||||
from_secret: HARBOR_USERNAME
|
||||
password:
|
||||
from_secret: HARBOR_PASSWORD
|
||||
|
||||
# تگگذاری
|
||||
tags:
|
||||
- latest
|
||||
- ${CI_COMMIT_SHA:0:8}
|
||||
|
||||
dockerfile: build/docker/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
|
||||
build_args:
|
||||
- VERSION=${CI_COMMIT_SHA:0:8}
|
||||
- BUILD_DATE=${CI_PIPELINE_CREATED}
|
||||
- PYTHON_VERSION=3.11
|
||||
- NODE_VERSION=20
|
||||
|
||||
labels:
|
||||
- org.opencontainers.image.created=${CI_PIPELINE_CREATED}
|
||||
- org.opencontainers.image.source=${CI_REPO_LINK}
|
||||
- org.opencontainers.image.url=${CI_REPO_LINK}
|
||||
- org.opencontainers.image.revision=${CI_COMMIT_SHA}
|
||||
- org.opencontainers.image.version=${CI_COMMIT_SHA:0:8}
|
||||
- org.opencontainers.image.title=Peikarband Landing
|
||||
- org.opencontainers.image.description=Peikarband hosting platform landing page
|
||||
|
||||
cache: inline
|
||||
provenance: true
|
||||
push: true
|
||||
|
||||
when:
|
||||
- event: [push, tag, manual]
|
||||
branch: main # معمولاً فقط روی برنچ اصلی پوش انجام میشود
|
||||
|
||||
timeout: 30m
|
||||
172
build/docker/Dockerfile
Normal file
172
build/docker/Dockerfile
Normal file
@@ -0,0 +1,172 @@
|
||||
# Peikarband Platform - Production Dockerfile
|
||||
# Multi-stage build for optimized image size and security
|
||||
|
||||
# Build arguments
|
||||
ARG PYTHON_VERSION=3.11
|
||||
ARG NODE_VERSION=20
|
||||
ARG VERSION=latest
|
||||
ARG BUILD_DATE
|
||||
|
||||
# ============================================
|
||||
# Stage 1: Builder
|
||||
# ============================================
|
||||
FROM python:${PYTHON_VERSION}-slim AS builder
|
||||
|
||||
# Re-declare ARGs for this stage
|
||||
ARG NODE_VERSION=20
|
||||
ARG VERSION=latest
|
||||
ARG BUILD_DATE
|
||||
|
||||
LABEL maintainer="Peikarband Team <dev@peikarband.ir>"
|
||||
LABEL org.opencontainers.image.title="Peikarband Landing"
|
||||
LABEL org.opencontainers.image.description="Peikarband hosting platform landing page"
|
||||
LABEL org.opencontainers.image.version="${VERSION}"
|
||||
LABEL org.opencontainers.image.created="${BUILD_DATE}"
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
g++ \
|
||||
make \
|
||||
curl \
|
||||
gnupg \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Node.js (required for Reflex)
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install bun (required by Reflex for frontend build)
|
||||
# Retry mechanism for network issues
|
||||
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 || (echo "Failed to install bun after 5 attempts" && exit 1)
|
||||
|
||||
# Add bun to PATH
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
# Copy only requirements first (for better layer caching)
|
||||
COPY requirements.txt .
|
||||
|
||||
# Install Python dependencies in user space
|
||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
||||
pip install --no-cache-dir --user -r requirements.txt
|
||||
|
||||
# Copy application code (excluding .dockerignore items)
|
||||
COPY --chown=root:root . .
|
||||
|
||||
# Build and export Reflex app for production
|
||||
# Note: API_URL will be updated at runtime from environment variable
|
||||
# Export creates .web directory with frontend static files
|
||||
# bun is now pre-installed, so reflex export won't try to download it
|
||||
RUN python -m reflex export --no-zip
|
||||
|
||||
# Aggressive cleanup to reduce layer size
|
||||
# NOTE: Keep .web directory - it contains frontend static files
|
||||
RUN set -ex && \
|
||||
# Remove Python cache
|
||||
find /build -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
||||
find /build -type f -name "*.pyc" -delete && \
|
||||
find /build -type f -name "*.pyo" -delete && \
|
||||
# Remove development files
|
||||
rm -rf /build/tests /build/docs /build/tools && \
|
||||
rm -rf /build/.git /build/.github /build/.vscode && \
|
||||
rm -rf /build/venv /build/env && \
|
||||
# Remove node_modules but KEEP .web (frontend static files)
|
||||
rm -rf /build/node_modules && \
|
||||
# Remove large duplicate assets from root
|
||||
rm -f /build/*.gif /build/*.mp4 /build/*.mov 2>/dev/null || true && \
|
||||
# Keep only necessary configs
|
||||
find /build -type f -name "docker-compose*.yml" -delete && \
|
||||
find /build -type f -name "Makefile" -delete
|
||||
|
||||
# ============================================
|
||||
# Stage 2: Runtime
|
||||
# ============================================
|
||||
FROM python:${PYTHON_VERSION}-slim
|
||||
|
||||
# Re-declare ARGs for this stage
|
||||
ARG PYTHON_VERSION=3.11
|
||||
ARG VERSION=latest
|
||||
ARG BUILD_DATE
|
||||
|
||||
# Build info
|
||||
ENV VERSION=${VERSION} \
|
||||
BUILD_DATE=${BUILD_DATE}
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install runtime dependencies only
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
ca-certificates \
|
||||
tini \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
# Install Node.js runtime
|
||||
ARG NODE_VERSION=20
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
# Create non-root user first
|
||||
RUN groupadd -r -g 1000 peikarband && \
|
||||
useradd -r -u 1000 -g peikarband -m -s /bin/bash peikarband && \
|
||||
mkdir -p /app/logs /app/uploads /app/.reflex
|
||||
|
||||
# Copy Python dependencies from builder to user home
|
||||
COPY --from=builder /root/.local /home/peikarband/.local
|
||||
|
||||
# Copy application code from builder
|
||||
COPY --from=builder /build /app
|
||||
|
||||
# Copy and set up runtime script
|
||||
COPY --chown=peikarband:peikarband tools/scripts/update-env-json.sh /app/tools/scripts/update-env-json.sh
|
||||
RUN chmod +x /app/tools/scripts/update-env-json.sh
|
||||
|
||||
# Fix ownership
|
||||
RUN chown -R peikarband:peikarband /home/peikarband/.local /app
|
||||
|
||||
# Add version info (must be before USER switch)
|
||||
RUN echo "${VERSION}" > /app/.version && \
|
||||
chown peikarband:peikarband /app/.version
|
||||
|
||||
# Security: Remove unnecessary setuid/setgid permissions
|
||||
RUN find / -perm /6000 -type f -exec chmod a-s {} \; 2>/dev/null || true
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH=/home/peikarband/.local/bin:$PATH \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONHASHSEED=random \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||||
REFLEX_ENV=prod \
|
||||
ENVIRONMENT=prod
|
||||
|
||||
# Switch to non-root user
|
||||
USER peikarband
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 3000 8000
|
||||
|
||||
# Health check with better error handling
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD curl -f -s -o /dev/null -w "%{http_code}" http://localhost:8000/ping | grep -q "200" || exit 1
|
||||
|
||||
# Use tini as init system for proper signal handling
|
||||
# Update .web/env.json from API_URL env var, then run the app
|
||||
ENTRYPOINT ["/usr/bin/tini", "--", "/app/tools/scripts/update-env-json.sh"]
|
||||
|
||||
# Run application (both frontend and backend)
|
||||
CMD ["python", "-m", "reflex", "run", "--env", "prod"]
|
||||
|
||||
54
build/docker/Dockerfile.base
Normal file
54
build/docker/Dockerfile.base
Normal file
@@ -0,0 +1,54 @@
|
||||
# Base Image for Peikarband Projects
|
||||
#
|
||||
# This Dockerfile should be in a SEPARATE repository: peikarband/base
|
||||
# It's kept here for reference only.
|
||||
#
|
||||
# Purpose: Pre-installed build tools (Python, Node.js, bun, gcc, etc.)
|
||||
# Registry: hub.peikarband.ir/peikarband/base:latest
|
||||
#
|
||||
# This image is built once and cached, making subsequent builds much faster
|
||||
# All Peikarband projects should use this base image
|
||||
|
||||
ARG PYTHON_VERSION=3.11
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
FROM python:${PYTHON_VERSION}-slim AS base
|
||||
|
||||
LABEL maintainer="Peikarband Team <dev@peikarband.ir>"
|
||||
LABEL description="Base image with Python, Node.js, bun, and build tools"
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
g++ \
|
||||
make \
|
||||
curl \
|
||||
gnupg \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Node.js (required for Reflex)
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install bun (required by Reflex for frontend build)
|
||||
# Retry mechanism for network issues
|
||||
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 || (echo "Failed to install bun after 5 attempts" && exit 1)
|
||||
|
||||
# Add bun to PATH
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
# Verify installations
|
||||
RUN python --version && \
|
||||
node --version && \
|
||||
npm --version && \
|
||||
bun --version
|
||||
|
||||
92
build/docker/docker-compose.yml
Normal file
92
build/docker/docker-compose.yml
Normal file
@@ -0,0 +1,92 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# PostgreSQL Database
|
||||
postgres:
|
||||
image: postgres:14-alpine
|
||||
container_name: peikarband-db
|
||||
environment:
|
||||
POSTGRES_USER: ${DB_USER:-peikarband}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-peikarband}
|
||||
POSTGRES_DB: ${DB_NAME:-peikarband}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U peikarband"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Redis Cache
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: peikarband-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Peikarband Application
|
||||
app:
|
||||
build: .
|
||||
container_name: peikarband-app
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://peikarband:peikarband@postgres:5432/peikarband
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
- CELERY_BROKER_URL=redis://redis:6379/1
|
||||
- CELERY_RESULT_BACKEND=redis://redis:6379/2
|
||||
- SECRET_KEY=${SECRET_KEY}
|
||||
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
|
||||
- ENVIRONMENT=production
|
||||
volumes:
|
||||
- ./:/app
|
||||
restart: unless-stopped
|
||||
|
||||
# Celery Worker
|
||||
celery:
|
||||
build: .
|
||||
container_name: peikarband-celery
|
||||
command: celery -A src.infrastructure.tasks.celery_app worker -l info
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://peikarband:peikarband@postgres:5432/peikarband
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
- CELERY_BROKER_URL=redis://redis:6379/1
|
||||
- CELERY_RESULT_BACKEND=redis://redis:6379/2
|
||||
volumes:
|
||||
- ./:/app
|
||||
restart: unless-stopped
|
||||
|
||||
# Flower (Celery Monitoring)
|
||||
flower:
|
||||
build: .
|
||||
container_name: peikarband-flower
|
||||
command: celery -A src.infrastructure.tasks.celery_app flower
|
||||
depends_on:
|
||||
- redis
|
||||
- celery
|
||||
ports:
|
||||
- "5555:5555"
|
||||
environment:
|
||||
- CELERY_BROKER_URL=redis://redis:6379/1
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
|
||||
Reference in New Issue
Block a user