راه اندازی مرحله به مرحله 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