دیپلوی حرفهای NextJs روی VPS با Docker
احتمالاً برای خیلیها پیش اومده که پروژه روی لپتاپ کاملاً درست کار میکنه، اما وقتی روی سرور دیپلوی میشه با خطاهای عجیب، نسخههای ناسازگار پکیجها یا تنظیمات متفاوت سیستمعامل روبهرو میشن. گاهی حتی یک آپدیت ساده روی سرور میتونه کل محیط اجرا رو به هم بریزه.
اینجاست که Docker وارد میشه.
داکر به شما اجازه میده کل محیط اجرای اپلیکیشن رو داخل یک کانتینر بستهبندی کنید؛ یعنی نسخه Node.js، پکیجها، تنظیمات و هر چیزی که پروژه برای اجرا نیاز داره. نتیجه اینه که برنامه دقیقاً به همون شکلی که روی سیستم شما کار میکنه، روی سرور هم اجرا میشه. فرقی نداره سرور Ubuntu باشه یا Debian، VPS داخل ایران باشه یا خارج از کشور.
البته قرار نیست بعد از خوندن این مقاله تبدیل به متخصص Docker یا Next.js بشید. هدف اینه که یک مسیر عملی و قابل استفاده برای دیپلوی پروژه روی VPS یاد بگیرید؛ مسیری که امروزه توسط بسیاری از تیمهای توسعه برای اجرای پایدار و قابل تکرار پروژهها استفاده میشه.
در این آموزش از نصب Docker روی سرور شروع میکنیم، پروژه Next.js یا Node.js رو کانتینری میکنیم، با Docker Compose اجراش میکنیم و در نهایت با Nginx و SSL اون رو برای استفاده در محیط Production آماده میکنیم.
میتونی قبل شروع این مقاله هارو بخونی که کمکت کنه بهتر متوجه اینجا بشی و همچنین یجورایی پیشنیاز هستن:
- داکر چیست و چرا ازش استفاده کنیم
- لینوکس چیست (معمولا سیستم عامل vps ها لینوکس هست)
- SSH چیست (اتصال به سرور از سیستم شخصی)
- کامند های ترمینال لینوکس (شاید بخواید یاد بگیرید، خیلی کارا میشه باهاشون کرد)
۱. نصب Docker روی VPS
آپدیت سیستم:
apt update && apt upgrade -y
نصب Docker:
curl -fsSL https://get.docker.com | sh
فعالسازی و بررسی:
systemctl enable docker systemctl start docker docker -v
۲. نصب Docker Compose
apt install docker-compose-plugin -y docker compose version
بعد از نصب داکر کامپوز ورژنش رو چک کنید که اون هم اوکی باشه
۳. میرورهای داخلی — ویژه کاربران ایران
به دلیل قطعیهای مکرر اینترنت بینالملل در ایران، دانلود مستقیم از Docker Hub اغلب ناموفقه. استفاده از میرور داخلی یک ضرورته، نه یک پیشنهاد اختیاری.
DevNeeds
یکی از کاملترین میرورهای داخلی ایران. پوشش میده:
- Docker Hub
- پکیج منیجرهای زبانهای مختلف (npm، pip، composer، cargo و ...)
- نسخههای مختلف PostgreSQL
ArvanCloud
زیرساخت ابری ایرانی با میرور برای:
فعال کردن میرور Docker
فایل تنظیمات daemon رو ویرایش کن:
nano /etc/docker/daemon.json
محتوای زیر رو وارد کن:
{
"registry-mirrors": [
"https://mirror.devneeds.ir",
"https://docker.arvancloud.ir"
]
}
بعد از ذخیره، Docker رو ریاستارت کن:
systemctl daemon-reload systemctl restart docker docker info | grep -A5 "Registry Mirrors"
برای میرور سیستمعامل، بالا لینک کردم دقیقا کجا باید برید — آدرس دقیق sources.list برای هر distro اونجاست.
۴. آمادهسازی پروژه Node.js
ساختار استاندارد:
app/ ├── src/ │ └── index.js ├── package.json ├── package-lock.json ├── Dockerfile └── docker-compose.yml
۵. ساخت Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
اینجا حواستون باشه نوع بیلدتون چیه توی Next Js، مثلا اگر standalone باشه باید از "node /server.js" برای شروع سرو کردن استفاده کنید:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
دلیل copy کردن package.json قبل از سورس: Docker لایهها رو cache میکنه. اگر سورس کد عوض بشه ولی dependency عوض نشه، npm install مجدداً اجرا نمیشه و build سریعتره.
۶. ساخت docker-compose.yml
version: "3.8"
services:
app:
build: .
container_name: node_app
restart: unless-stopped
ports:
- "3000:3000"
environment:
- NODE_ENV=production
deploy:
resources:
limits:
memory: 512M
۷. اجرا و دیپلوی
اجرای اولیه:
docker compose up -d --build
بررسی وضعیت و لاگ:
docker ps docker logs -f node_app
آپدیت بعد از هر بار تغییر کد:
git pull docker compose up -d --build
این یعنی: بدون نیاز به نصب Node روی سرور، بدون conflict dependency، بدون خراب شدن محیط.
۸. Nginx به عنوان Reverse Proxy
نصب:
apt install nginx -y
کانفیگ در /etc/nginx/sites-available/myapp:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
فعالسازی:
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/ nginx -t systemctl restart nginx
۹. SSL رایگان با Let's Encrypt
apt install certbot python3-certbot-nginx -y certbot --nginx -d your-domain.com
قبل از اجرا مطمئن شو DNS دامنهات به IP سرور اشاره میکنه و پورت ۸۰ باز باشه.
همچنین اینجا بازم باید بگم که بخاطر شرایط اینترنت ایران، بهتره که ssl رو هم از روش های جایگذین ست کنید که renew بشه که توی devneeds (بخش SSL) مثلا توضیح داده شده به صورت رایگان گرفتن ssl.
۱۰. تنظیمات Production
در docker-compose.yml از restart: unless-stopped استفاده کن تا container بعد از ریاستارت سرور هم بالا بیاد.
برای دیدن لاگهای دقیقتر:
docker logs -f node_app docker inspect node_app
جمعبندی
ترکیب استاندارد برای یه دیپلوی حرفهای:
- Docker — اجرای ایزوله اپ
- Docker Compose — مدیریت سرویسها
- Nginx — reverse proxy و ورودی ترافیک
- SSL — امنیت ارتباط
- میرور داخلی — پایداری در شرایط ایران
| روش | مشکل اصلی |
|---|---|
| Node + PM2 مستقیم | وابستگی به سرور — هر تغییری میتونه محیط رو خراب کنه |
| نصب دستی | conflict dependency — قابل تکرار نیست |
| Docker + Compose | محیط ثابت — deploy یکسان روی همه سرورها |