داشتن یک VPS خوب عالی است، اما مدیریت دستی سرویسها—از PHP و Nginx گرفته تا MySQL و Redis—میتواند کابوس باشد. Docker این مشکل را حل میکند: هر سرویس در کانتینر ایزوله خودش اجرا میشود، با یک دستور docker compose up -d کل پروژه بالا میآید، و بدترین سناریو این است که با docker compose down همه چیز را ریست کنید.
در این راهنما، از صفر مطلق شروع میکنیم—نصب Docker روی VPS تازه، اجرای اولین کانتینر، نوشتن فایل docker-compose.yml برای یک پروژه واقعی، و در نهایت تنظیمات امنیتی و monitoring.
پیشنیازها
- VPS با Ubuntu 22.04 یا 24.04 (حداقل ۲ گیگ RAM، توصیه ۴ گیگ)
- دسترسی SSH با کاربر sudo
- حداقل ۲۰ گیگابایت فضای خالی (Imageهای Docker سریع حجم میگیرند!)
گام اول — اتصال و آمادهسازی سرور
ssh your-user@vps-ip
sudo apt update && sudo apt upgrade -y
پکیجهای پایه را نصب کنید:
sudo apt install -y ca-certificates curl gnupg lsb-release
گام دوم — نصب Docker Engine (روش رسمی)
Docker را از مخزن رسمی Docker—نه مخزن Ubuntu—نصب میکنیم. نسخه Ubuntu قدیمی است و باگ دارد.
# اضافه کردن GPG key رسمی Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# اضافه کردن مخزن Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
حالا Docker را نصب کنید:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
نکته مهم: docker-compose-plugin همان Docker Compose V2 است که به صورت docker compose (با space، نه dash) اجرا میشود. نسخه قدیمی docker-compose منسوخ شده.
گام سوم — اجرای Docker بدون sudo
به صورت پیشفرض فقط root میتواند Docker اجرا کند. برای راحتی، کاربر خود را به گروه docker اضافه کنید:
sudo usermod -aG docker $USER
newgrp docker
حالا بدون sudo تست کنید:
docker run hello-world
اگر پیام Hello from Docker! را دیدید، همه چیز آماده است.
گام چهارم — اولین پروژه Docker: Nginx
بیایید با یک مثال ساده مطمئن شویم همه چیز کار میکند:
docker run -d --name my-nginx -p 8080:80 nginx:alpine
حالا در مرورگر به http://your-vps-ip:8080 بروید—باید صفحه پیشفرض Nginx را ببینید.
متوقف کردن کانتینر:
docker stop my-nginx
docker rm my-nginx
گام پنجم — Docker Compose: اجرای پروژه واقعی
حالا یک پروژه واقعی با Docker Compose اجرا میکنیم. فرض کنید یک اپلیکیشن Node.js با MongoDB دارید.
ساخت پوشه پروژه:
mkdir ~/myapp && cd ~/myapp
فایل docker-compose.yml را بسازید:
version: '3.8'
services:
app:
image: node:20-alpine
container_name: myapp-node
working_dir: /app
volumes:
- ./app:/app
ports:
- "3000:3000"
command: sh -c "npm install && node server.js"
depends_on:
mongo:
condition: service_healthy
restart: unless-stopped
networks:
- app-network
mongo:
image: mongo:7
container_name: myapp-mongo
volumes:
- mongo_data:/data/db
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-secret}
restart: unless-stopped
networks:
- app-network
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh --quiet
interval: 10s
timeout: 5s
retries: 5
mongo-express:
image: mongo-express:latest
container_name: myapp-mongo-ui
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_PASSWORD:-secret}
ME_CONFIG_MONGODB_URL: mongodb://admin:${MONGO_PASSWORD:-secret}@mongo:27017/
depends_on:
mongo:
condition: service_healthy
restart: unless-stopped
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mongo_data:
اجرای پروژه:
docker compose up -d
مشاهده وضعیت:
docker compose ps
docker compose logs -f
متوقف کردن:
docker compose down
گام ششم — مدیریت Volumeها و بکآپ
دادههای داخل کانتینر ephemeral هستند—با حذف کانتینر، دادهها از بین میروند. برای ذخیره دائمی از Volume استفاده کنید.
مشاهده Volumeها:
docker volume ls
بکآپ گرفتن از Volume (مثلاً دیتابیس MongoDB):
docker run --rm -v myapp_mongo_data:/data -v $(pwd):/backup alpine \
tar czf /backup/mongo-backup-$(date +%Y%m%d).tar.gz -C /data .
بازگردانی بکآپ:
docker run --rm -v myapp_mongo_data:/data -v $(pwd):/backup alpine \
tar xzf /backup/mongo-backup-20260801.tar.gz -C /data
گام هفتم — امنیت کانتینرها
۱. همیشه از imageهای رسمی و trusted استفاده کنید
# خوب ✅
docker pull node:20-alpine
docker pull nginx:alpine
# بد ❌
docker pull some-random-user/unknown-image
۲. کانتینرها را با کاربر non-root اجرا کنید
services:
app:
image: node:20-alpine
user: "1000:1000" # UID:GID کاربر غیر-root
۳. Resource Limits تنظیم کنید
بدون limit، یک کانتینر میتواند تمام RAM و CPU سرور را مصرف کند:
services:
app:
image: node:20-alpine
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
۴. اسکن امنیتی imageها
docker scout quickview nginx:alpine
docker scout cves nginx:alpine
۵. فایروال Docker را دور نزنید
Docker به صورت پیشفرض قوانین iptables را دستکاری میکند و ممکن است پورتها را بدون اجازه UFW باز کند. برای جلوگیری:
sudo nano /etc/docker/daemon.json
{
"iptables": false,
"ip-forward": false
}
و سپس:
sudo systemctl restart docker
گام هشتم — Monitoring و عیبیابی
Docker Stats (لحظهای)
docker stats
Portainer — مدیریت گرافیکی Docker
docker volume create portainer_data
docker run -d \
-p 9443:9443 -p 8000:8000 \
--name portainer --restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
حالا در مرورگر به https://your-vps-ip:9443 بروید—یک داشبورد کامل برای مدیریت Docker دارید.
لاگهای متمرکز با Dozzle
docker run -d --name dozzle \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 8080:8080 \
amir20/dozzle:latest
پاکسازی دورهای
Docker imageهای قدیمی و استفاده نشده میتوانند گیگابایتها فضا اشغال کنند:
# پاکسازی imageهای بدون تگ
docker image prune -a -f
# پاکسازی volumeهای استفاده نشده
docker volume prune -f
# پاکسازی همه چیز (با احتیاط!)
docker system prune -a --volumes -f
یک cron job هفتگی برای پاکسازی خودکار تنظیم کنید:
crontab -e
0 3 * * 0 docker system prune -a -f --filter "until=168h"
مقایسه: Docker روی VPS vs Kubernetes
| معیار | Docker Compose روی VPS | Kubernetes |
|---|---|---|
| پیچیدگی راهاندازی | ⭐ کم | ⭐⭐⭐⭐⭐ بالا |
| مناسب برای | ۱-۱۰ کانتینر، استارتاپها | ۲۰+ کانتینر، Enterprise |
| Auto-scaling | ❌ دستی | ✅ خودکار |
| Load balancing | نیاز به Nginx دستی | ✅ داخلی (Ingress) |
| هزینه | فقط هزینه VPS | هزینه cluster + management |
| یادگیری | ۱-۲ روز | ۱-۳ ماه |
برای ۹۰٪ پروژهها، Docker Compose روی یک VPS خوب بیش از حد کافی است. وقتی به ۱۰+ میکروسرویس رسیدید و نیاز به auto-scaling و zero-downtime deployment دارید، آن وقت Kubernetes را در نظر بگیرید.
نکته تیم افرادین: سرورهای ابری افرادین با Docker Engine و Docker Compose از پیش نصب شده و بهینهشده عرضه میشوند. کافیست فایل
docker-compose.ymlخود را push کنید و پروژه در چند دقیقه بالا میآید. Portainer و Dozzle هم با یک کلیک قابل نصب هستند.