Darslik · 2026-08-16 · ~4 daqiqa o‘qiladi · o'rta
Docker'siz production deploy: uv + gunicorn + systemd + nginx
Mundarija
Hamma joyda "deploy = Docker" deb o'rgatishadi. Lekin qo'lingizda 1GB RAM'lik, eski OS'li arzon VPS bo'lsa (yoki bitta serverda boshqa loyihalar ham yashasa), Docker ortiqcha yuk bo'lishi mumkin. Shu sayt — solijonov.uz — aynan shunday serverda, Docker'siz ishlayapti. Mana to'liq retsept.
Arxitektura#
Internet → nginx (443, TLS) → gunicorn (127.0.0.1:8001) → Django
└── /static/ fayllarni to'g'ridan-to'g'ri beradi
nginx — tashqi eshik: HTTPS'ni tugatadi, static fayllarni o'zi beradi (Python'ga yuk tushmaydi), qolganini gunicorn'ga uzatadi. systemd — "qorovul": server qayta yuklansa yoki jarayon yiqilsa, o'zi qayta ko'taradi.
1. Python va kutubxonalar — uv bilan#
Eski serverlarda tizim Python'i qadimiy bo'ladi. uv buni bir buyruq bilan hal qiladi:
curl -LsSf https://astral.sh/uv/install.sh | sh
uv python install 3.13
cd /opt/mysite && uv sync --frozen --no-dev
--frozen — lockfile'dagi aynan shu versiyalar o'rnatiladi: lokalda qanday
ishlagan bo'lsa, serverda ham shunday.
2. Gunicorn'ni systemd ostiga qo'yish#
/etc/systemd/system/mysite.service:
[Unit]
Description=Mysite (gunicorn)
After=network.target
[Service]
WorkingDirectory=/opt/mysite
Environment=DJANGO_SETTINGS_MODULE=config.settings.prod
ExecStart=/opt/mysite/.venv/bin/gunicorn config.wsgi:application --bind 127.0.0.1:8001 --workers 2
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now mysite
Restart=always + enable — ikki qator, lekin "server reboot bo'ldi, sayt
o'lik" degan tungi qo'ng'iroqlardan qutqaradi. Workers soni: kichik server uchun
2 yetadi (formula: 2 × CPU + 1 — lekin RAM'ga qarab kamaytiring).
3. Nginx — proxy va static#
/etc/nginx/conf.d/mysite.conf:
server {
listen 80;
server_name mysite.uz www.mysite.uz;
location /static/ {
alias /opt/mysite/staticfiles/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
X-Forwarded-Proto muhim: Django SECURE_PROXY_SSL_HEADER orqali so'rov
HTTPS'da kelganini shundan biladi.
4. HTTPS — certbot#
uv tool install certbot --with certbot-nginx
certbot --nginx -d mysite.uz -d www.mysite.uz
Certbot nginx konfigga TLS blokini o'zi yozadi. Yangilanishni cron'ga qo'ying:
17 3,15 * * * certbot renew --quiet — sertifikat muddati o'z-o'zidan uzayadi.
5. Deploy skripti#
Har deploy — bitta buyruq bo'lishi kerak. Bizniki qisqartirilgan ko'rinishda:
rsync -az --delete --exclude .venv --exclude .env ./ server:/opt/mysite/
ssh server "cd /opt/mysite && uv sync --frozen --no-dev \
&& .venv/bin/python manage.py collectstatic --noinput \
&& .venv/bin/python manage.py migrate --noinput \
&& systemctl restart mysite"
.envni ataylab sync qilmaymiz — sirlar serverda qoladi, tasodifan o'chmasin.
Docker qachon kerak, qachon yo'q#
Docker'siz yaxshi: bitta-ikkita loyiha, kichik server, tez boshlash, RAM tanqis. Docker yaxshi: ko'p xizmatli stack (Postgres, Redis, workerlar), jamoa, "mening mashinamda ishlagan edi" muammosi. Bu tanlov diniy emas — amaliy: bizga bugun yengillik kerak edi, ertaga server kattalashsa, compose faylimiz tayyor turibdi.
Savol qolsa — Telegram'da yozing, shu mavzuda video dars ham qilaman.