برنامه نویسی

راه اندازی مرحله به مرحله nextpalestine: نمای کلی

شیرجه عمیق به بعدی فلسطین:
پلتفرم وبلاگ نویسی منبع باز با ویژگی های غنی ساخته شده با Next.js و Nest.js

آیا می خواهید به راحتی یک پلت فرم وبلاگ نویسی زیبا بسازید؟ برنامه وب منبع باز ما nextpalestine را بررسی کنید!
پلت فرم وبلاگ نویسی بدون دردسر با ویرایشگر قدرتمند، مدیریت کاربر و موارد دیگر. منبع باز در GitHub!، این ارائه به قابلیت های nextpalestine می پردازد.

nextpalestine بر روی یک ساختار mono-repo ساخته شده است:

.
├── frontend
│   └── package.json
├── backend
│   └── package.json
└── package.json

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

root package.json:

{
  "name": "nextpalestine-monorepo",
  "version": "0.1.0",
  "private": true,
  "license": "GPL",
  "description": "Blogging platform",
  "repository": {
    "type": "git",
    "url": ""
  },
  "author": "Adel Benyahia ",
  "authors": ["Adel Benyahia "],
  "engines": {
    "node": ">=18"
  },
  "devDependencies": {
    "husky": "^8.0.0",
    "npm-run-all": "^4.1.5"
  },
  "scripts": {
    "backend": "npm run start:dev -w backend",
    "frontend": "npm run dev -w frontend",
    "frontend:prod": "npm run build -w frontend && npm run start:prod -w frontend",
    "backend:prod": "npm run build -w backend && npm run start:prod -w backend",
    "dev": "npm-run-all --parallel backend frontend",
    "start": "npm-run-all --parallel backend:prod frontend:prod",
    "docker:build": "docker compose down && docker compose up -d --build",
    "prepare": "husky install"
  },
  "workspaces": ["backend", "frontend"],
  "lint-staged": {
    "**/*.{js,jsx,ts,tsx}": ["npx prettier --write", "npx eslint --fix"]
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده می کنیم

بسته npm-run-all برای اجرای چندین دستور به صورت همزمان، به عنوان مثال دستور start دو دستور را به صورت موازی شروع می کند backend و frontend .

اگر پوشه .husky را در پوشه root بررسی کنیم، از Husky برای اجرای قلاب‌های پیش‌فرض استفاده می‌شود.

.
├── .husky
   └── _
   └── pre-commit
├── frontend
   └── package.json
├── backend
   └── package.json
└── package.json
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پوشه ./husky:

ما از هاسکی استفاده می‌کنیم تا کد خود را قبل از اجرای آن اصلاح کنیم، و برای سریع‌تر کردن این فرآیند از بسته دوم استفاده می‌کنیم: lint-staged تا فقط کد مرحله‌ای را پر کند (کد تازه اضافه شده یا اصلاح شده)


#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# Exit immediately if any command exits with a non-zero status.
set -e

echo 'Linting project before committing'
npx lint-staged
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

compose.yaml

این فایل برای ساختن یک برنامه docker شده خود میزبانی استفاده می‌شود که می‌توانیم آن را در هر سیستمی که داکر را اجرا می‌کند مستقر کنیم.

برای اجرای صحیح Deploy برنامه ما در docker باید:

1- مخزن ما را کلون کنید: git clone [https://github.com/adelpro/nextpalestine.git](https://github.com/adelpro/nextpalestine.git)

2- یک فایل .env.production در پوشه frontend تراز شده با env.example (در همان پوشه) ایجاد کنید.

3- یک فایل .env.production در پوشه backend تراز شده با env.example (در همان پوشه) ایجاد کنید.

4- دویدن: docker compose up -d

اکنون فایل compose.yaml را توضیح می دهیم

services:
  # Fontend: NextJs
  frontend:
    env_file:
      - ./frontend/.env.production
    container_name: nextpalestine-frontend
    image: nextpalestine-frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile
      args:
        - DOCKER_BUILDKIT=1
    ports:
      - 3540:3540
    restart: unless-stopped
    depends_on:
      backend:
        condition: service_healthy
    volumes:
      - /app/node_modules
      # For live reload if the source or env changes
      - ./frontend/src:/app/src

    networks:
      - app-network
  # Backend: NestJS
  backend:
    container_name: nextpalestine-backend
    image: nextpalestine-backend
    env_file:
      - ./backend/.env.production
    build:
      context: ./backend
      dockerfile: Dockerfile
      args:
        - DOCKER_BUILDKIT=1
    ports:
      - 3500:3500
    restart: unless-stopped
    depends_on:
      mongodb:
        condition: service_healthy
    volumes:
      - backend_v_logs:/app/logs
      - backend_v_public:/app/public
      - /app/node_modules
      # For live reload if the source or env changes
      - ./backend/src:/app/src
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://backend:3500/health || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 20s
    networks:
      - app-network

  # Database: Mongodb
  mongodb:
    container_name: mongodb
    image: mongo:latest
    restart: unless-stopped
    ports:
      - 27018:27017
    env_file:
      - ./backend/.env.production
    networks:
      - app-network
    volumes:
      - mongodb_data:/data/db
      - /etc/timezone:/etc/timezone:ro
      #- type: bind
      #    source: ./mongo-entrypoint
      #    target: /docker-entrypoint-initdb.d/
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 20s

  # Database UI: Mongo Express
  mongo-express:
    image: mongo-express:1.0.2-20-alpine3.19
    container_name: mongo-express
    restart: always
    ports:
      - 8081:8081
    env_file:
      - ./backend/.env.production
    depends_on:
      - mongodb
    networks:
      - app-network
volumes:
  backend_v_logs:
    name: nextpalestine_v_backend_logs
  backend_v_public:
    name: nextpalestine_v_backend_public
  mongodb_data:
    name: nextpalestine_v_mongodb_data
    driver: local
networks:
  app-network:
    driver: bridge
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، ما تصاویر چهارم را داریم

1- mongo-express:

mongo-express یک رابط مدیریت MongoDB مبتنی بر وب است

2- مونگو:

تصویر رسمی داکر مونگو، که در آن یک بررسی سلامت اضافه کرده‌ایم، بعداً در تصویر باطن به آن نیاز خواهیم داشت.

    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 20s
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما همچنین فایل .env را از پوشه backend بارگذاری کرده ایم

    env_file:
      - ./backend/.env.production
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما به این متغیرهای env نیاز داریم:

MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=password
MONGO_DATABASE_NAME=database
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و ما در حال ایجاد یک حجم ثابت (نام‌گذاری‌شده) برای تداوم داده‌ها بین ساخت‌های مختلف هستیم، خط دوم یک هک برای همگام‌سازی منطقه زمانی بین تصویر docker و میزبانی است که آن را اجرا می‌کند، این تضمین می‌کند که مُهرهای زمانی در پایگاه داده شما با میزبان مطابقت داشته باشد. منطقه زمانی سیستم

    volumes:
      - mongodb_data:/data/db
      - /etc/timezone:/etc/timezone:ro
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پورت در معرض دید را نیز به (27018) تغییر دادیم، 27018:27017 این از هرگونه تضاد با هر پایگاه داده mongodb نصب شده در سیستم میزبان با پورت پیش فرض (27017) جلوگیری می کند.

3- Backend (Nest.js)

  backend:
    container_name: nextpalestine-backend
    image: nextpalestine-backend
    env_file:
      - ./backend/.env.production
    build:
      context: ./backend
      dockerfile: Dockerfile
      args:
        - DOCKER_BUILDKIT=1
    ports:
      - 3500:3500
    restart: unless-stopped
    depends_on:
      mongodb:
        condition: service_healthy
    volumes:
      - backend_v_logs:/app/logs
      - backend_v_public:/app/public
      - /app/node_modules
      # For live reload if the source or env changes
      - ./backend/src:/app/src
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://backend:3500/health || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 20s
    networks:
      - app-network
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این تصویر بر روی ./backend/Dockerfile با استفاده از آرگومان DOCKER_BUILDER=1 ساخته شده است، این باعث افزایش سرعت ساخت و ذخیره سازی حافظه پنهان می شود.

  • متغیر Env از ./backend/.env.production بارگیری می شود.
  • این به تصویر mongodb بستگی دارد، تا زمانی که تصویر مونگو به طور کامل و سالم شروع نشود، تصویر باطن شروع نمی شود.
  • تصویر باطن دارای بررسی سلامتی خود است که ما در تصویر جلویی (Next.js) استفاده خواهیم کرد.
  • ما در حال ادامه گزارش‌ها و پوشه‌های عمومی با استفاده از حجم‌های نام‌گذاری شده هستیم.
  • این جلد: /app/node_modules برای تداوم node_module استفاده می شود.
  • این جلد: ./backend/src:/app/src برای بارگذاری مجدد تصویر در صورت تغییر کد.
  • بندر 3500:3500 برای Backend استفاده می شود.

اکنون Dockerfile بک‌اند (در پوشه باطن) را توضیح می‌دهیم.

ARG NODE=node:21-alpine3.19

# Stage 1: builder
FROM ${NODE} AS builder

# Combine commands to reduce layers
RUN apk add --no-cache libc6-compat \
    && apk add --no-cache curl \
    && addgroup --system --gid 1001 nodejs \
    && adduser --system --uid 1001 nestjs

WORKDIR /app

COPY --chown=nestjs:nodejs package*.json ./

RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn \
    yarn install --frozen-lockfile

COPY --chown=nestjs:nodejs . .

ENV NODE_ENV production

# Generate the production build. The build script runs "nest build" to compile the application.
RUN yarn build

# Install only the production dependencies and clean cache to optimize image size.
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn \
    yarn install --production --frozen-lockfile && yarn cache clean

USER nestjs

# Stage 2: runner
FROM ${NODE} AS runner

RUN apk add --no-cache libc6-compat \
    && apk add --no-cache curl \
    && addgroup --system --gid 1001 nodejs \
    && adduser --system --uid 1001 nestjs

WORKDIR /app

# Set to production environment
ENV NODE_ENV production

# Copy only the necessary files
COPY --chown=nestjs:nodejs --from=builder /app/dist ./dist
COPY --chown=nestjs:nodejs --from=builder /app/logs ./logs
COPY --chown=nestjs:nodejs --from=builder /app/public ./public
COPY --chown=nestjs:nodejs --from=builder /app/node_modules ./node_modules
COPY --chown=nestjs:nodejs --from=builder /app/package*.json ./

# Set Docker as non-root user
USER nestjs

EXPOSE 3500

ENV HOSTNAME "0.0.0.0"

CMD ["node", "dist/main.js"]
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این یک فایل docker چند مرحله ای است که بر روی Linux alpine ساخته شده است، ما ابتدا یک بسته اضافی را نصب می کنیم libc6-comat سپس یک کاربر جداگانه برای برنامه ما برای یک لایه امنیتی اضافی ایجاد کنید.

در حال نصب هستیم curl ، از آن برای بررسی سالم بودن تصویرمان استفاده خواهیم کرد.

سپس پوشه های مورد نیاز را با مجوزهای مناسب کپی می کنیم

ما در نهایت برنامه خود را با شکایت اجرا می کنیم node dist/main.js

3- frontend (Nextt.js)

# Args
ARG NODE=node:21-alpine3.19

# Stage 1: builder
FROM ${NODE} AS builder

RUN apk add --no-cache libc6-compat \
    && addgroup --system --gid 1001 nodejs \
    && adduser --system --uid 1001 nextjs

WORKDIR /app

COPY --chown=nextjs:nodejs package*.json ./

RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn \
    yarn install --frozen-lockfile

COPY --chown=nextjs:nodejs . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1

ENV NEXT_PRIVATE_STANDALONE true
ENV NODE_ENV production

# Generate the production build
RUN yarn build

# Install only the production dependencies and clean cache
RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn \
    yarn install --frozen-lockfile --production && yarn cache clean

USER nextjs

# Stage 2: runner
FROM ${NODE} AS runner

RUN apk add --no-cache libc6-compat \
    && addgroup --system --gid 1001 nodejs \
    && adduser --system --uid 1001 nextjs

WORKDIR /app

ENV NODE_ENV production

# Uncomment the following line in case you want to disable telemetry during runtime.
 ENV NEXT_TELEMETRY_DISABLED 1

COPY --from=builder /app/public ./public 

# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
# Copy next.conf only if it's not the default
COPY --from=builder --chown=nextjs:nodejs /app/next.config.js ./
COPY --from=builder --chown=nextjs:nodejs /app/package*.json ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./        
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

# Set Docker as non-root user
USER nextjs

EXPOSE 3540

ENV PORT 3540

ENV HOSTNAME "0.0.0.0"

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
CMD ["node", "server.js"]

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این Dockerfile چند مرحله ای:

  • ما از یک تصویر باریک لینوکس بر اساس alpine استفاده می کنیم
  • ما در حال ایجاد یک کاربر جدید به عنوان یک لایه امنیتی اضافی هستیم
  • ما از یک تکنیک ویژه برای استفاده مجدد از حافظه پنهان نخ از ساخت‌های پیش‌نمایش استفاده می‌کنیم (DOCKER_BUILDKIT باید فعال باشد)

--mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn \

  • می‌توانیم (به‌صورت اختیاری) تله‌متری Next.js را با استفاده از این خط غیرفعال کنیم:

ENV NEXT_TELEMETRY_DISABLED 1

  • سپس ما Next.js خود را به عنوان یک برنامه مستقل می سازیم و پوشه های لازم را مدیریت می کنیم
  • ما یک پورت سفارشی تنظیم کردیم: 3540

ENV PORT 3540

  • و شروع برنامه با استفاده از: node server.js

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا