Tarkibga o'tish

05 β€” Ilovani qo'lda serverga joylash

⬅️ Oldingi: 04 β€” Tarmoq va server xavfsizligi Β· 🏠 README Β· Keyingi: 06 β€” Docker nima: konteynerlar ➑️

Bu bobda: nazariyani bir chetga qo'yib, haqiqiy ishni qilamiz β€” kichik lekin ishlaydigan Node.js (Express) "vazifalar" (todo) REST API yozamiz (GET /tasks, POST /tasks, xotirada), uni lokalda ishga tushiramiz, so'ng qo'lda VPS serverga joylaymiz: ssh bilan ulanish, Node o'rnatish (nodesource yoki nvm), kodni git clone (yoki scp/rsync) bilan olib borish, npm install, node app.js va curl bilan tekshirish. Hammasi ishlaydi β€” lekin keyin bu yo'lning oltita og'rig'ini sezasiz: terminal yopilsa ilova o'ladi, "menda ishlaydi" muammosi, ochiq xunuk port, HTTPS yo'qligi, har yangilashda qo'lda downtime, va qayta tiklashning og'irligi. Har og'riq β€” kitobning keyingi qaysidir bobida hal qilinadi; oxirida "og'riqlar -> yechimlar xaritasi" jadvalini ko'rasiz. Bu bob β€” kitobning qolgan qismi uchun motivatsiya: nima uchun Docker, CI/CD, Nginx, systemd va Kubernetes kerakligini his qildiradi.


Muammo: ilova lokalda ishlaydi, endi nima?

Tasavvur qiling β€” ilovangizni yozib bo'ldingiz. node app.js deysiz, brauzerda localhost:3000 ochiladi, hammasi zo'r. Lekin bu faqat sizning kompyuteringizda. Dunyodagi boshqa hech kim uni ko'ra olmaydi: kompyuteringiz uxlab qolsa yoki uni o'chirsangiz, ilova ham yo'qoladi.

"Internetga chiqarish" β€” buni deploy (joylashtirish) deyiladi: ilovani doimo yoqilgan, internetga ulangan serverga ko'chirib, u yerda ishlatib turish. Server haqiqiy bo'lsa, ilova ham haqiqatan ishlaydi. Bu bobda buni eng oddiy, eng "qo'l bilan" usulda qilamiz. Maqsad β€” ilovani ishlatish, va shu jarayonning qanchalik mashaqqatli ekanini his qilish. Chunki aynan shu mashaqqat keyingi 20+ bobning sababi.

πŸ“Œ Bu bob motivatsiya bobi. Biz "to'g'ri" deploy qilmaymiz β€” ataylab eng sodda yo'ldan boramiz, og'riqlarni sanaymiz, keyin har birini kitobning tegishli bobiga ulagan holatda yo'l xaritasini chizamiz.


Namuna ilova: vazifalar (todo) API

Butun kitob bo'ylab bizga deploy qilish uchun bitta namuna ilova kerak. U kichkina bo'lishi kerak (diqqatimiz deployda, ilova mantig'ida emas), lekin haqiqiy bo'lishi shart β€” port tinglaydigan, so'rovga javob beradigan, internetga chiqarsa ma'no kasb etadigan. Backend dasturchilarning ko'pchiligi tushunadigan narsa β€” REST API. Shuning uchun kichik "vazifalar" (todo) API yozamiz.

Ilovaning arxitekturasi juda oddiy: klient (brauzer yoki curl) HTTP so'rov yuboradi, Express uni qabul qiladi, marshrut (route) ishlaydi, javob qaytadi. Vazifalar hozircha xotirada (oddiy massivda) saqlanadi β€” ma'lumotlar bazasi keyinroq.

Vazifalar todo API arxitekturasi: klient Express ilovasiga so'rov yuboradi, express.json middleware tanani o'qiydi, GET va POST marshrutlar xotiradagi massiv bilan ishlaydi

Ikki fayl kifoya. Avval package.json:

{
  "name": "vazifalar-api",
  "version": "1.0.0",
  "type": "module",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^5.1.0"
  }
}

ℹ️ "type": "module" β€” zamonaviy ESM (import/export) sintaksisini yoqadi. "scripts.start" esa npm start deganda nima ishga tushishini bildiradi β€” bu odat keyin server va Docker'da qo'l keladi.

Endi app.js β€” ilovaning o'zi:

import express from "express";

const app = express();
app.use(express.json());

// Vazifalar xotirada saqlanadi (server qayta ishga tushsa yo'qoladi)
let vazifalar = [
  { id: 1, matn: "DevOps kitobini o'qish", bajarildi: false },
];
let keyingiId = 2;

// Barcha vazifalarni qaytarish
app.get("/tasks", (req, res) => {
  res.json(vazifalar);
});

// Yangi vazifa qo'shish
app.post("/tasks", (req, res) => {
  const matn = req.body?.matn;
  if (!matn) {
    return res.status(400).json({ xato: "matn maydoni shart" });
  }
  const vazifa = { id: keyingiId++, matn, bajarildi: false };
  vazifalar.push(vazifa);
  res.status(201).json(vazifa);
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Vazifalar API http://localhost:${PORT} da ishlamoqda`);
});

Bu yerda muhim bir narsa bor: port process.env.PORT || 3000 orqali olinadi. Ya'ni PORT muhit o'zgaruvchisi (environment variable) berilsa β€” o'sha, aks holda 3000. Bu β€” production ilovaning birinchi qoidasi: sozlamalar kodda emas, muhitda. Serverda portni o'zgartirish uchun kodga tegmaysiz.

Lokalda sinab ko'ramiz:

npm install
npm start
Vazifalar API http://localhost:3000 da ishlamoqda

Ikkinchi terminalda curl bilan tekshiramiz:

curl http://localhost:3000/tasks
[{"id":1,"matn":"DevOps kitobini o'qish","bajarildi":false}]

Yangi vazifa qo'shamiz (POST):

curl -X POST http://localhost:3000/tasks \
  -H "Content-Type: application/json" \
  -d '{"matn":"Serverga deploy qilish"}'
{"id":2,"matn":"Serverga deploy qilish","bajarildi":false}

Ishladi. Endi xuddi shu ilovani boshqa kishilar ham ko'ra oladigan qilishimiz kerak β€” ya'ni serverga olib chiqamiz.

πŸ’‘ Bu kichik ilova β€” kitobning "tirik qahramoni". Keyin uni Docker konteyneriga joylaymiz, CI/CD pipeline'iga ulaymiz, Nginx ortiga qo'yamiz, HTTPS beramiz va oxirida Kubernetes'da masshtablaymiz. Hozir esa β€” eng oddiy yo'l.


Bizga server kerak

Server β€” bu shunchaki doimo yoqilgan, internetga doimiy IP bilan ulangan kompyuter. Uni o'zingiz sotib olishingiz shart emas: cloud provayderlardan (DigitalOcean, Hetzner, AWS Lightsail, Vultr va h.k.) oyiga bir necha dollarga VPS (Virtual Private Server β€” virtual xususiy server) ijaraga olasiz. Yangi hisoblar uchun ko'pincha bepul kredit beriladi.

VPS olganingizda sizga uchta narsa beriladi: IP manzil (masalan 203.0.113.10), foydalanuvchi (odatda root yoki ubuntu) va kirish usuli (parol yoki, to'g'ri yo'l β€” SSH kalit, 04-bobda ko'rganmiz). Biz Ubuntu 26.04 LTS (yoki hali qo'llab-quvvatlanadigan 24.04 LTS) serveridan foydalanamiz.

⚠️ Bu bobdagi server qadamlari illustrativ β€” ular haqiqiy VPSda bajariladi va shuning uchun o'z serveringizda ishlab ko'rishingiz kerak. Lokal kompyuterda apt, ufw, ssh root@... ishlamaydi (yoki ma'no kasb etmaydi). Buyruqlar to'g'ri yozilgan β€” ularni arzon VPS olib, o'sha yerda sinab ko'ring.


Qadamma-qadam: qo'lda deploy

Quyidagi olti qadam β€” qo'lda deployning klassik yo'li. Har biri qo'l mehnati, har biri keyin avtomatlashtiriladigan narsa.

Qo'lda deploy oltita qadami: lokaldan ssh, Node o'rnatish, kodni olib borish, npm install, node app.js, port ochish va curl bilan tekshirish

1-qadam: serverga ssh bilan ulanish

Lokal terminalingizdan serverga kiramiz (04-bobda SSH kalitni sozlagansiz):

ssh ubuntu@203.0.113.10

Endi terminalingiz server ichida ishlaydi. Buyruqlar serverda bajariladi.

2-qadam: Node.js o'rnatish

Server toza Ubuntu β€” unda Node yo'q. Ikki keng tarqalgan usul bor.

Usul A β€” NodeSource (tizim bo'yicha, server uchun afzal):

curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt-get install -y nodejs
node -v
v22.x.x

Usul B β€” nvm (Node Version Manager, bir nechta versiyani boshqarish uchun qulay):

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# yangi qobiq oching yoki: source ~/.bashrc
nvm install 22
nvm use 22
node -v

πŸ’‘ Server uchun odatda NodeSource (Usul A) afzal β€” Node butun tizim uchun bir marta o'rnatiladi. nvm bir foydalanuvchi bir nechta loyihada turli Node versiyalarini ishlatadigan holatda qulay. Aynan shu "qaysi versiya?" savoli β€” keyinroq bizni Docker'ga olib boradigan og'riqlardan biri.

3-qadam: kodni serverga olib borish

Eng toza yo'l β€” kod GitHub'da bo'lsa, serverda git clone:

sudo apt-get install -y git
git clone https://github.com/foydalanuvchi/vazifalar-api.git
cd vazifalar-api

Agar kod faqat lokalda bo'lsa, lokal terminaldan (server emas) rsync yoki scp bilan yuborasiz:

# Lokal kompyuterda bajariladi:
rsync -av --exclude node_modules ./vazifalar-api/ ubuntu@203.0.113.10:~/vazifalar-api/

πŸ“Œ node_modules'ni hech qachon ko'chirmang β€” u yuzlab megabayt va platformaga bog'liq bo'lishi mumkin. Serverda npm install qiling, u kerakli paketlarni o'sha server uchun o'rnatadi. Shuning uchun --exclude node_modules.

4-qadam: bog'liqliklarni o'rnatish

Server ichida, loyiha papkasida:

npm install

npm package.json dagi dependencies'ni o'qib, Express'ni va uning bog'liqliklarini node_modules/ ga o'rnatadi.

5-qadam: ilovani ishga tushirish va portni ochish

node app.js
Vazifalar API http://localhost:3000 da ishlamoqda

Ilova ishlamoqda β€” lekin server firewall (ufw, 04-bob) 3000-portni tashqaridan bloklayotgan bo'lishi mumkin. Buni boshqa terminaldan (yana bir ssh seansi) ochamiz:

sudo ufw allow 3000/tcp

⚠️ 3000-portni to'g'ridan-to'g'ri butun internetga ochish β€” vaqtinchalik, "ishlasin" yechimi. Production'da ilova porti tashqariga ochilmaydi; oldida Nginx turadi va faqat 80/443 ochiq bo'ladi (16-18-boblar). Hozircha β€” sezish uchun ochamiz.

6-qadam: tashqaridan tekshirish

Lokal kompyuteringizdan (yoki brauzerdan) serverning IP'siga murojaat qilamiz:

curl http://203.0.113.10:3000/tasks
[{"id":1,"matn":"DevOps kitobini o'qish","bajarildi":false}]

Tabriklaymiz β€” ilovangiz internetda. Dunyoning istalgan nuqtasidan http://203.0.113.10:3000/tasks ochib uni ko'rish mumkin.

Endi... bir nafas oling. Chunki bu quvonch uzoq davom etmaydi.


Va mana β€” og'riqlar boshlanadi

Og'riq 1: terminalni yopsangiz, ilova o'ladi

ssh seansidan chiqasiz (yoki shunchaki terminalni yopasiz) β€” va ilova to'xtaydi. Chunki node app.js sizning terminal seansingizga "bog'langan" jarayon. Seans tugasa β€” jarayon ham.

Vaqtinchalik yamoq β€” nohup yoki screen/tmux:

# nohup: jarayon terminalga bog'lanmaydi, log faylga yoziladi
nohup node app.js > app.log 2>&1 &
# yoki screen: nomli seans ochib, undan "uzilib" chiqasiz
screen -S vazifalar
node app.js
# Ctrl+A keyin D bosib uziling β€” ilova ishlab qoladi

Bu ishlaydi, lekin xunuk: server qayta yuklansa ilova o'z-o'zidan ko'tarilmaydi, qulab tushsa qayta ishga tushmaydi, loglar tartibsiz. Asl yechim β€” operatsion tizimning xizmat menejeri, ya'ni systemd: u ilovani fon xizmati qiladi, qulasa avtomatik qayta ishga tushiradi, server o'chib-yonsa o'zi ko'taradi.

βœ… Yechim: systemd (19-bob). nohup/screen β€” vaqtinchalik plaster; systemd service β€” to'g'ri yechim.

Og'riq 2: "menda ishlaydi-ku!"

Lokalingizda Node 22 bor edi, serverda esa 18 o'rnatib qo'ydingiz β€” va ilova ishlamaydi. Yoki lokal Linux, server boshqa distributiv; yoki bir paket lokalda bor, serverda yo'q. Klassik gap: "Menda ishlaydi-ku!" β€” lekin serverda yo'q.

Sabab β€” muhit farqi: Node versiyasi, OS, tizim kutubxonalari, muhit o'zgaruvchilari. Har bir serverni qo'lda bir xil holatga keltirish β€” qiyin va xatoga moyil.

βœ… Yechim: Docker (06–11-boblar). Ilovani konteynerga β€” Node, kod va barcha bog'liqliklar bilan bitta "qutiga" β€” joylaymiz. Bu quti lokalda ham, serverda ham, hamkasbingizda ham aynan bir xil ishlaydi. "Menda ishlaydi" muammosi yo'qoladi.

Og'riq 3: http://203.0.113.10:3000 β€” xunuk va xavfli

Foydalanuvchiga "saytim 203.0.113.10:3000 da" deb aytib bo'lmaydi. Bizga domen nomi (masalan vazifalar.uz) va odatdagi 80/443 portlar kerak β€” :3000siz. Bundan tashqari, ilova portini to'g'ridan internetga ochish β€” xavfsizlik nuqtai nazaridan yomon: ilova bevosita hujum yuzasiga aylanadi.

βœ… Yechim: Nginx reverse proxy (16–17-boblar). Nginx 80/443-portda turadi, so'rovlarni ichkaridagi localhost:3000 ga uzatadi. Foydalanuvchi :3000 ni ko'rmaydi, ilova porti tashqariga ochilmaydi, bir nechta ilovaga yuk taqsimlash ham mumkin bo'ladi.

Og'riq 4: HTTPS yo'q

URL http:// β€” https:// emas. Ya'ni trafik shifrlanmagan: parollar, tokenlar ochiq uzatiladi, brauzer "Xavfsiz emas" deb ogohlantiradi. Bugungi internetda HTTPSsiz sayt β€” qabul qilib bo'lmas holat.

βœ… Yechim: Let's Encrypt + Certbot (18-bob). Bepul, avtomatik yangilanadigan TLS sertifikat. http:// https:// ga aylanadi, brauzerda qulf belgisi paydo bo'ladi.

Og'riq 5: har yangilashda β€” yana qo'lda, yana downtime

Kodda bitta satr o'zgartirdingizmi? Yana hamma narsa boshidan: ssh, git pull, npm install, eski jarayonni o'ldirish, qaytadan ishga tushirish. Bu vaqtda sayt bir necha soniya/daqiqa ishlamaydi (downtime). Kuniga o'n marta deploy qilsangiz β€” bu jahannam. Va bir kun yarim tunda, charchagan holatda, bir qadamni o'tkazib yuborib β€” production'ni buzasiz.

βœ… Yechim: CI/CD β€” GitHub Actions (12–15-boblar). Har git pushda avtomatik: test ishlaydi, image quriladi, serverga deploy bo'ladi β€” odam aralashuvisiz. Git & GitHub kitobida Actions asoslarini ko'rganmiz; bu yerda uni deploy uchun ishlatamiz.

Og'riq 6: qayta tiklash β€” butunlay qo'lda

Server qulab tushsa yoki yangisini olsangiz, hamma narsa boshidan: Node o'rnatish, firewall, foydalanuvchi, ilova... yodingizda bormi har bir buyruq? Yo'q. "Qaysi paketni o'rnatgan edim?" degan savol qoladi.

βœ… Yechim: Infrastructure as Code β€” Ansible/Terraform (27-bob). Butun serverni kod bilan tasvirlaysiz; bitta buyruq bilan noldan tiklanadigan, takrorlanadigan infratuzilma. Kubernetes (21–24-boblar) esa ilovani avtomatik tiklash va masshtablashni o'z zimmasiga oladi.


Og'riqlar -> yechimlar xaritasi

Yuqoridagi olti og'riqning hammasi β€” bekorga emas. Har biri kitobning aniq bir bobida hal qilinadi. Mana to'liq xarita:

Qo'lda deployning olti og'rig'i va har birini yechadigan keyingi bob jadvali

# Qo'lda deploy og'rig'i Yechim Bob
1 Terminal yopilsa ilova to'xtaydi; qulasa ko'tarilmaydi systemd xizmat (auto-restart) 19
2 "Menda ishlaydi" β€” Node/OS/bog'liqlik farqi Docker konteyner 06–11
3 Ochiq :3000 port β€” xunuk va xavfli Nginx reverse proxy 16–17
4 HTTPS yo'q β€” trafik shifrlanmagan Let's Encrypt / Certbot 18
5 Har yangilash qo'lda + downtime CI/CD (GitHub Actions) 12–15
6 Qayta tiklash butunlay qo'lda IaC (Ansible/Terraform), K8s 27, 21–24

πŸ“Œ Shu jadval β€” kitobning yo'l xaritasi. Keyingi har bir bobni o'qiyotganda "bu qaysi og'riqni yechyapti?" deb o'zingizdan so'rang. 20-bob esa hammasini birlashtirib, namuna ilovani to'liq productionga chiqaradi.

Qo'lda deploy yomon emas β€” uni bir marta bilish shart, chunki avtomatlashtirish ostida aynan shu qadamlar bajariladi. Lekin uni har kuni qo'lda takrorlash β€” DevOps aynan yo'q qiladigan narsa. Keyingi bobdan boshlab biz har bir qadamni avtomatik, takrorlanadigan va ishonchli qilamiz. Birinchi to'xtash β€” Docker: "menda ishlaydi" muammosining yakuni.


05-bob mashqlari

Oson

  1. Namuna vazifalar-api ilovasini lokalda yarating (app.js + package.json), npm install va npm start qiling, so'ng curl http://localhost:3000/tasks bilan boshlang'ich vazifani ko'ring.
  2. POST /tasks ga curl -X POST ... -d '{"matn":"yangi vazifa"}' yuboring va 201 javobini hamda yangi id ni ko'ring. So'ng GET /tasks qaytarganda ikki vazifa borligini tasdiqlang.
  3. Ilovani PORT=4000 npm start bilan boshqa portda ishga tushiring. process.env.PORT qanday ishlayotganini tushuntiring.
  4. POST /tasks ga matn maydonisiz (-d '{}') so'rov yuboring. Qaysi status kod qaytadi va nega?

O'rta

  1. Qo'lda deployning olti qadamini (ssh -> Node -> kod -> npm install -> ishga tushirish -> tekshirish) o'z so'zlaringiz bilan ketma-ketlik sifatida yozing. Har qadam yonida "bu qadam qo'lda bo'lgani uchun qanday xato kelib chiqishi mumkin?" deb bitta xavfni belgilang.
  2. node_modules papkasini nega serverga ko'chirmaslik kerakligini tushuntiring va rsync buyrug'ida uni --exclude bilan chiqarib tashlang.
  3. nohup node app.js > app.log 2>&1 & buyrug'ining har bir qismini (nohup, > app.log, 2>&1, &) ajratib tushuntiring. Bu yechim nega vaqtinchalik?
  4. Olti og'riqning har birini mos yechim/bobga ulang (xotiradan jadval tuzing). Qaysi og'riq sizni eng ko'p qiziqtiradi va nega?

Qiyin

  1. Namuna ilovaga uchinchi marshrut qo'shing: DELETE /tasks/:id β€” berilgan id li vazifani o'chirsin, topilsa 204, topilmasa 404 qaytarsin. Lokalda curl -X DELETE bilan sinab ko'ring.
  2. NodeSource (Usul A) va nvm (Usul B) bilan Node o'rnatishni solishtiring: qaysi biri server uchun, qaysi biri ko'p-versiyali ish stoli uchun afzal va nega? Har birining bitta kamchiligini ayting.
  3. "Menda ishlaydi" muammosini boshdan kechiring (yoki tasavvur qiling): namuna ilovani Node 22 talab qiladigan kodga ataylab o'zgartiring (masalan yangi sintaksis ishlating), so'ng eski Node bo'lgan muhitda ishga tushirilsa nima bo'lishini tushuntiring. Docker buni qanday yo'qotadi?
  4. Bitta bash skript (deploy.sh) yozing β€” qo'lda deployning server tomonidagi qadamlarini birlashtirsin: git pull, npm install, eski jarayonni to'xtatib nohup bilan qayta ishga tushirish. Skript yozgach, nega bu hali ham "to'g'ri" deploy emasligini (downtime, auto-restart yo'q, atomik emas) ayting.
Yechim β€” 9

app.js ga quyidagi marshrutni qo'shing (boshqa marshrutlar yonida):

// Vazifani o'chirish
app.delete("/tasks/:id", (req, res) => {
  const id = Number(req.params.id);
  const oldingi = vazifalar.length;
  vazifalar = vazifalar.filter((v) => v.id !== id);
  if (vazifalar.length === oldingi) {
    return res.status(404).json({ xato: "Vazifa topilmadi" });
  }
  res.status(204).end();
});

Sinash:

curl -i -X DELETE http://localhost:3000/tasks/1   # 204 No Content
curl -i -X DELETE http://localhost:3000/tasks/999 # 404 Not Found

Number(req.params.id) β€” URL parametri har doim satr bo'lgani uchun id ni songa aylantiramiz. 204 β€” "muvaffaqiyatli, lekin qaytaradigan tana yo'q". Topilmasa 404.

Yechim β€” 10

NodeSource (Usul A) β€” Node'ni tizim paketi sifatida butun serverga o'rnatadi. Server uchun afzal: bitta versiya, barcha foydalanuvchi va xizmatlar uchun bir xil, systemd xizmati uchun ishonchli yo'l. Kamchiligi: bir serverda bir vaqtda bir nechta Node versiyasini saqlash qiyin; yangilash uchun apt bilan ishlash kerak.

nvm (Usul B) β€” har foydalanuvchi o'z uy papkasiga bir nechta Node versiyasini o'rnatadi va nvm use bilan almashtiradi. Ish stoli / ishlab chiqish muhiti uchun afzal: turli loyihalar turli Node versiyalarini talab qilganda qulay. Kamchiligi: foydalanuvchi qobig'iga bog'liq (source ~/.bashrc), shuning uchun systemd xizmati uchun yo'lni aniq ko'rsatish kerak; har foydalanuvchida alohida o'rnatiladi.

Xulosa: serverda NodeSource, ko'p-loyihali ish stolida nvm. Va aslida "qaysi Node versiyasi?" savolining o'zi β€” Docker bu og'riqni butunlay yo'q qiladigan sababdir (versiya image ichida qotiriladi).

Yechim β€” 11

Masalan app.js ga ataylab yangi sintaksis/API qo'shasiz (faqat yangi Node'da bor narsa). Eski Node bo'lgan serverda node app.js qilsangiz β€” SyntaxError yoki is not a function kabi xato bilan qulaydi, lokalingizda esa muammosiz ishlardi. Mana shu β€” "menda ishlaydi-ku" muammosining mohiyati: ilova muhitga bog'liq, muhit esa serverdan serverga farq qiladi.

Docker buni qanday yo'qotadi: ilovani FROM node:22 kabi aniq versiyali base image ustiga quramiz. Endi kod, Node versiyasi va barcha bog'liqliklar bitta image ichida qotiriladi. Bu image lokalda ham, serverda ham, har qanday CI'da ham β€” bitobit bir xil. Serverda "qaysi Node?" degan savol umuman yo'qoladi: konteyner o'z Node'ini olib keladi. (Buni 06–08-boblarda batafsil ko'ramiz.)

Yechim β€” 12

Sodda deploy.sh (server tomonida, loyiha papkasida bajariladi):

#!/usr/bin/env bash
set -euo pipefail

echo "1/4 Eng yangi kodni olish..."
git pull origin main

echo "2/4 Bog'liqliklarni o'rnatish..."
npm install --omit=dev

echo "3/4 Eski jarayonni to'xtatish (bo'lsa)..."
pkill -f "node app.js" || true

echo "4/4 Ilovani qayta ishga tushirish..."
nohup node app.js > app.log 2>&1 &

echo "Tayyor. Loglar: app.log"

set -euo pipefail β€” xato bo'lsa skript darhol to'xtaydi (03-bobdagi xavfsiz skript odati). pkill ... || true β€” jarayon bo'lmasa ham skript yiqilmasin.

Nega bu hali ham "to'g'ri" deploy emas: - Downtime bor β€” eski jarayon o'lib, yangisi ko'tarilguncha sayt javob bermaydi. - Auto-restart yo'q β€” server qayta yuklansa yoki ilova qulasa, hech kim uni ko'tarmaydi (nohup buni qilmaydi). - Atomik emas β€” npm install yarim yo'lda buzilsa, ilova nuqson holatda qoladi, qaytarish (rollback) yo'q. - Hali ham qo'lda ishga tushiriladi β€” skriptni kimdir ssh qilib chaqirishi kerak.

To'g'ri yechim: ilovani systemd xizmati qilish (19-bob, auto-restart + reboot'da ko'tarilish) va deployni CI/CD ga ko'chirish (12–15-boblar, git pushda avtomatik), ideal holatda Docker image orqali (atomik, rollback oson).


⬅️ Oldingi: 04 β€” Tarmoq va server xavfsizligi Β· 🏠 README Β· Keyingi: 06 β€” Docker nima: konteynerlar ➑️