diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c13779c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,27 @@ +node_modules +dist +.git +.gitignore +.env +.env.local +.env.development.local +.env.test.local +.env.production.local +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.DS_Store +.vscode +.idea +*.swp +*.swo +*~ +coverage +.nyc_output +.cache +README.md +CHANGELOG.md +*.md +!public/**/*.md + diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..ca68229 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,76 @@ +# راهنمای Docker + +این پروژه با Docker containerize شده است و می‌توانید آن را به راحتی build و اجرا کنید. + +## پیش‌نیازها + +1. **نصب Docker Desktop** (برای Windows): + - دانلود از: https://www.docker.com/products/docker-desktop/ + - نصب و راه‌اندازی Docker Desktop + - اطمینان حاصل کنید که Docker در حال اجرا است + +2. **نصب Docker Compose** (معمولاً با Docker Desktop نصب می‌شود) + +## دستورات Docker + +### Build کردن Image + +```bash +docker build -t pwa-react-app . +``` + +### اجرای Container + +```bash +docker run -d -p 3000:80 --name pwa-react-app pwa-react-app +``` + +یا با استفاده از Docker Compose: + +```bash +docker-compose up -d +``` + +### مشاهده لاگ‌ها + +```bash +docker logs pwa-react-app +``` + +یا با Docker Compose: + +```bash +docker-compose logs -f +``` + +### توقف Container + +```bash +docker stop pwa-react-app +docker rm pwa-react-app +``` + +یا با Docker Compose: + +```bash +docker-compose down +``` + +### دسترسی به اپلیکیشن + +بعد از اجرا، اپلیکیشن در آدرس زیر در دسترس است: +- http://localhost:3000 + +## ساختار فایل‌های Docker + +- `Dockerfile`: فایل اصلی برای build کردن image +- `.dockerignore`: فایل‌ها و پوشه‌هایی که در build نادیده گرفته می‌شوند +- `docker-compose.yml`: فایل تنظیمات برای اجرای آسان با Docker Compose +- `nginx.conf`: تنظیمات Nginx برای سرو کردن فایل‌های static + +## نکات مهم + +1. قبل از build، مطمئن شوید که `.env` فایل‌های شما در `.dockerignore` هستند (برای امنیت) +2. پورت پیش‌فرض در `docker-compose.yml` روی 3000 تنظیم شده است +3. برای تغییر پورت، فایل `docker-compose.yml` را ویرایش کنید + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f4f570b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Build stage +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy source code +COPY . . + +# Build the application +RUN npm run build + +# Production stage +FROM nginx:alpine + +# Copy built files from builder stage +COPY --from=builder /app/dist /usr/share/nginx/html + +# Copy nginx configuration +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Expose port 80 +EXPOSE 80 + +# Start nginx +CMD ["nginx", "-g", "daemon off;"] + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..54cd406 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + container_name: pwa-react-app + ports: + - "3000:80" + restart: unless-stopped + environment: + - NODE_ENV=production + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health", "||", "exit", "1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..53dd836 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,42 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Handle client-side routing (SPA) + location / { + try_files $uri $uri/ /index.html; + } + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Don't cache HTML files + location ~* \.html$ { + expires -1; + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } + + # Health check endpoint + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } +} +