VPS ga deploy — serverga o'rnatish va yangilash
Muammodan boshlaylik
Image lar registry da (38-dars), CI ularni avtomatik yasaydi (41-dars). Endi bo'sh VPS bor: Ubuntu 24.04, 2 CPU, 4 GB, IP manzil va root paroli. Undan ishlayotgan, HTTPS li, avtomatik qayta tiklanadigan production gacha — qadam-baqadam.
1. Serverni tayyorlash
ssh root@45.12.34.56
# Tizimni yangilash
apt update && apt upgrade -y
# Alohida foydalanuvchi (root bilan ishlamaslik)
adduser deploy
usermod -aG sudo deploy
# SSH kalit bilan kirish (kompyuteringizdan)
# ssh-copy-id deploy@45.12.34.56
SSH xavfsizligi
/etc/ssh/sshd_config da:
PermitRootLogin no
PasswordAuthentication no
systemctl restart ssh
[!WARNING]
PasswordAuthentication nodan oldin SSH kalit bilan kirish ishlashini yangi terminalda tekshiring — aks holda serverdan o'zingizni qulflab qo'yasiz.
Firewall
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Eslatma (25-dars): Docker ports: UFW ni chetlab o'tadi — shuning uchun compose da faqat proxy ning 80/443 portlari ochiq bo'lishi kerak.
2. Docker o'rnatish
curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy
systemctl enable docker
# Qayta kiring va tekshiring
docker version
docker compose version
Log hajmini cheklash
Standart holatda konteyner loglari cheksiz o'sadi va bir kuni diskni to'ldiradi. /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
systemctl restart docker
Har bir konteyner uchun maksimal 30 MB log.
3. Loyiha fayllari
Serverga manba kod kerak emas — faqat compose fayllar va konfiguratsiya:
/opt/dokon/
├── compose.yaml
├── Caddyfile
├── .env # sirlar (chmod 600)
└── backups/
# /opt/dokon/compose.yaml
name: dokon
services:
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports: ["80:80", "443:443", "443:443/udp"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
networks: [frontend]
api:
image: ghcr.io/firdavsdev07/dokon-api:${API_TAG:-latest}
restart: unless-stopped
env_file: .env
networks: [frontend, backend]
deploy:
resources:
limits: { memory: 512M }
depends_on:
baza:
condition: service_healthy
baza:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?}
MYSQL_DATABASE: dokon
MYSQL_USER: dokon
MYSQL_PASSWORD: ${DB_PASSWORD:?}
volumes:
- mysql-data:/var/lib/mysql
networks: [backend]
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "--silent"]
interval: 5s
retries: 20
networks:
frontend:
backend:
internal: true
volumes:
caddy-data:
caddy-config:
mysql-data:
# Caddyfile
dokon.uz {
reverse_proxy api:3000
}
cd /opt/dokon
chmod 600 .env
# Yopiq registry uchun (read:packages ruxsatli token)
echo $GHCR_TOKEN | docker login ghcr.io -u firdavsdev07 --password-stdin
docker compose up -d
docker compose ps
DNS da dokon.uz → server IP (A yozuvi) — va bir necha soniyadan keyin https://dokon.uz ishlaydi.
4. Yangilash (deploy)
cd /opt/dokon
export API_TAG=sha-b7e1d04
docker compose pull api
docker compose up -d api
Compose faqat image o'zgargan xizmatni qayta yaratadi. Bu qadamlarni 41-darsdagi CI avtomatik bajaradi.
Orqaga qaytish (rollback)
export API_TAG=sha-a3f9c2b # oldingi ishlagan versiya
docker compose up -d api
Aniq teglar (38-dars) bo'lgani uchun — bir soniyalik ish.
[!INFO] Ma'lumotlar bazasi migratsiyalari orqaga qaytishni murakkablashtiradi. Qoida: migratsiyalar orqaga mos bo'lsin (ustun qo'shish — ha; nomini o'zgartirish yoki o'chirish — keyingi relizda). Shunda eski kod yangi sxema bilan ham ishlaydi.
Downtime haqida
up -d eski konteynerni to'xtatib, yangisini ishga tushiradi — bir necha soniya uzilish. Kichik loyihalar uchun odatda maqbul. Nolga yaqin uzilish uchun: ikki nusxa + proxy (blue-green), yoki Docker Swarm / Kubernetes ning rolling update i (44-dars).
5. Zaxira nusxa — avtomatik
21-darsdagi skript cron bilan:
#!/bin/sh
# /opt/dokon/backup.sh
set -e
cd /opt/dokon
SANA=$(date +%F_%H%M)
docker compose exec -T baza sh -c \
'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction dokon' \
| gzip > backups/dokon_$SANA.sql.gz
find backups -name "*.sql.gz" -mtime +14 -delete
crontab -e
# 0 3 * * * /opt/dokon/backup.sh >> /var/log/dokon-backup.log 2>&1
[!WARNING] Zaxira nusxa o'sha serverda — server yo'qolsa, zaxira ham yo'qoladi. Nusxalarni boshqa joyga ham yuboring (S3, Backblaze, boshqa server —
rclone). Va vaqti-vaqti bilan tiklashni sinab ko'ring.
6. Texnik xizmat
docker system df # disk qancha band
docker image prune -a -f --filter "until=168h"
docker compose logs --tail=100 api
docker stats --no-stream
Avtomatik xavfsizlik yangilanishlari:
apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
Deploy tekshiruv ro'yxati
[ ] SSH: kalit bilan, root va parol o'chirilgan
[ ] UFW: faqat 22, 80, 443
[ ] Docker log hajmi cheklangan
[ ] .env — chmod 600, Git da emas
[ ] Faqat proxy da ports; baza internal tarmoqda
[ ] restart: unless-stopped, resurs chegaralari
[ ] HTTPS ishlayapti (Caddy)
[ ] Zaxira — har kuni, boshqa joyga ham, tiklash sinalgan
[ ] Monitoring va ogohlantirishlar (43-dars)
Nima uchun shunday?
Nima uchun serverda manba kod va git pull yo'q — faqat compose fayl?
Chunki server — kod yoziladigan yoki build qilinadigan joy emas, tayyor artefaktlarni ishga tushiradigan joy. Kod CI da sinovdan o'tadi va image ga aylanadi; server faqat aniq teg bo'yicha shu image ni oladi. Natija: serverdagi holat to'liq bir necha fayl (compose.yaml, Caddyfile, .env) va volume lar bilan aniqlanadi. Server yo'qolsa — yangi VPS, Docker, shu fayllar, zaxiradan baza — va 15 daqiqada hammasi qaytadi. Server "uy hayvoni" emas, almashtiriladigan "chorva".
Xulosa
Eslab qoling:
- Server: alohida foydalanuvchi, SSH kalit, root/parol kirish o'chirilgan, UFW
- Docker:
get.docker.com,systemctl enable docker, log hajmi chegarasi (daemon.json) - Serverda:
compose.yaml+Caddyfile+.env— manba kod yo'q - Deploy:
API_TAG=... docker compose pull && up -d; rollback — eski teg - Migratsiyalar orqaga mos bo'lsin
- Zaxira: cron + boshqa joyga nusxa + tiklashni sinash
- Muntazam tozalash:
image prune,system df
Keyingi dars
43-dars: Loglar va monitoring — log driver lar, healthcheck, metrikalar