اجرای یک کانتینر معمولاً با یک فرمان جمع میشود. اما وقتی سایت به دیتابیس، فضای ذخیرهسازی و چند تنظیم وابسته است، فرمانهای پراکنده کمکم دردسر میشوند: کدام پورت را باز کرده بودیم؟ رمز کجا بود؟ بعد از ساخت دوباره کانتینر، آپلودها چه میشوند؟
Docker Compose این تنظیمات را در یک فایل قابل خواندن جمع میکند. در این آموزش یک سایت وردپرسی و دیتابیس MariaDB را راه میاندازیم. دیتابیس پورت عمومی ندارد و برای نصب اولیه وردپرس، از تونل SSH استفاده میکنیم.
قبل از شروع چه چیزهایی لازم است؟
یک VPS اوبونتو، دسترسی sudo و Docker Engine همراه Compose Plugin لازم دارید. اگر هنوز Docker را نصب نکردهاید، ابتدا آموزش نصب Docker روی Ubuntu را انجام دهید.
sudo docker version
sudo docker compose versionاگر دستور دوم شناخته نمیشود و قبلاً مخزن رسمی Docker را تنظیم کردهاید:
sudo apt update
sudo apt install docker-compose-pluginدر ادامه از دستور جدید docker compose استفاده میکنیم. فایلها را هم در یک پوشه مستقل میگذاریم تا پروژه با سرویسهای دیگر قاطی نشود.
۱. پوشه پروژه و فایل رمزها را بسازید
mkdir -p ~/netzo-wordpress
cd ~/netzo-wordpress
umask 077
mkdir -p secrets
openssl rand -hex 32 > secrets/db_password.txt
openssl rand -hex 32 > secrets/db_root_password.txt
chmod 600 secrets/*.txtدو رمز متفاوت ساخته شد: یکی برای کاربر برنامه و یکی برای مدیر دیتابیس. این فایلها را در مخزن عمومی Git، پیام گروهی یا اسکرینشات آموزشی قرار ندهید.
اگر پروژه را با Git نگه میدارید، در .gitignore بنویسید:
secrets/
backups/
.envℹ️ نکته: Secrets در Compose محلی به شکل فایل در اختیار سرویس مجاز قرار میگیرد. این قابلیت، فایل اصلی روی میزبان را رمزگذاری نمیکند؛ امنیت پوشه و نسخه پشتیبان آن همچنان مهم است.
۲. فایل Compose را آماده کنید
nano compose.yamlمحتوای زیر را قرار دهید:
name: netzo-wordpress
services:
db:
image: mariadb:11.4
restart: unless-stopped
environment:
MARIADB_DATABASE: wordpress
MARIADB_USER: wordpress
MARIADB_PASSWORD_FILE: /run/secrets/db_password
MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
secrets:
- db_password
- db_root_password
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
wordpress:
image: wordpress:php8.3-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
volumes:
- wordpress_data:/var/www/html
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
secrets:
db_password:
file: ./secrets/db_password.txt
db_root_password:
file: ./secrets/db_root_password.txt
volumes:
db_data:
wordpress_data:کدام قسمت این فایل مهمتر است؟
تنظیم | کاری که انجام میدهد |
|---|---|
| دو سرویس سایت و دیتابیس را تعریف میکند. |
| فایلهای سایت و داده دیتابیس را مستقل از عمر کانتینر نگه میدارد. |
| فایل رمز را فقط به سرویسهایی میدهد که آن را نیاز دارند. |
| شروع وردپرس را تا موفق شدن Healthcheck اولیه دیتابیس عقب میاندازد. |
| وردپرس را فقط روی Loopback میزبان در دسترس میگذارد. |
| برای لاگ هر کانتینر سقف اندازه و تعداد فایل تعیین میکند. |
نام db داخل شبکه Compose قابل استفاده است. وردپرس برای اتصال به MariaDB به IP عمومی VPS نیاز ندارد؛ دیتابیس هم در این فایل هیچ ports عمومی ندارد.
Healthcheck مشکل همه قطعیهای آینده را حل نمیکند. depends_on در اینجا ترتیب شروع اولیه را مدیریت میکند و جای منطق اتصال مجدد برنامه یا پایش سرویس را نمیگیرد.
۳. تنظیمات را بررسی و سرویسها را اجرا کنید
sudo docker compose config --quiet
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psاگر بررسی اول خطا داد، همانجا تورفتگی YAML، اسم فایل و مسیر Secrets را اصلاح کنید. دانلود Imageها هم به دسترسی سرور به Registry نیاز دارد؛ خطای شبکه را با تغییر تصادفی تنظیمات دیتابیس دنبال نکنید.
برای دیدن روند بالا آمدن سرویسها:
sudo docker compose logs --tail=100 db
sudo docker compose logs --tail=100 wordpress
curl -I http://127.0.0.1:8080کد 301 یا 302 میتواند مربوط به انتقال به صفحه نصب باشد. مهم این است که پاسخ HTTP بگیرید و لاگها خطای تکرارشونده نداشته باشند.
۴. نصب اولیه را از طریق تونل SSH انجام دهید
این فرمان را روی کامپیوتر خودتان اجرا کنید، نه داخل VPS:
ssh -L 8080:127.0.0.1:8080 user@SERVER_IPنام کاربری و IP را عوض کنید و نشست را باز نگه دارید. اگر SSH پورت دیگری دارد، گزینه -p را هم با مقدار درست اضافه کنید. بعد در مرورگر کامپیوتر خودتان به http://localhost:8080 بروید و نصب وردپرس را کامل کنید.
اگر پورت ۸۰۸۰ روی سیستم شخصی اشغال است، سمت اول را تغییر دهید:
ssh -L 18080:127.0.0.1:8080 user@SERVER_IPاین بار آدرس مرورگر http://localhost:18080 است.
🚨 هشدار: این مرحله برای نصب و آزمایش اولیه است. سایت عمومی به دامنه، HTTPS و Reverse Proxy نیاز دارد. پورت نمونه را برای رفع مشکل، بیبرنامه روی همه رابطها باز نکنید؛ انتشار پورت در Docker میتواند با انتظار شما از قواعد UFW متفاوت باشد.
قبل از استفاده عمومی، دامنه و HTTPS را مطابق راهنمای اتصال دامنه به VPS آماده کنید و Reverse Proxy را به 127.0.0.1:8080 متصل کنید. نشانی WordPress و Site URL هم باید از localhost به دامنه HTTPS نهایی تغییر کنند تا کاربران به آدرس محلی هدایت نشوند.
۵. توقف، راهاندازی و ماندگاری اطلاعات
برای توقف موقت و اجرای دوباره:
sudo docker compose stop
sudo docker compose startفرمان docker compose down کانتینرها و شبکه پروژه را جمع میکند؛ Volumeهای نامدار این نمونه بهطور پیشفرض باقی میمانند. اما افزودن -v میتواند همان دادهها را حذف کند.
🚨 هشدار: برای حل خطای اتصال دیتابیس، docker compose down -v راهحل عادی نیست. ممکن است دیتابیس و فایلهای سایت را از دست بدهید.
Volume هم بکاپ نیست. خرابی دیسک میزبان میتواند Volume و کانتینر را با هم از بین ببرد. از دیتابیس خروجی سازگار بگیرید، فایلهای وردپرس را با آن هماهنگ نگه دارید و نسخهای خارج از VPS ذخیره کنید.
خطاهای رایج و مسیر بررسی
وردپرس به دیتابیس وصل نمیشود
اول docker compose ps و لاگ db را ببینید. نام دیتابیس، کاربر و فایل رمز باید بین دو سرویس یکسان باشند. در دیتابیس از قبل ساختهشده، عوض کردن فایل رمز الزاماً رمز کاربر موجود را تغییر نمیدهد؛ تغییر رمز باید داخل خود دیتابیس هم مدیریت شود.
سایت از IP عمومی باز نمیشود
در این آموزش طبیعی است؛ وردپرس فقط روی Loopback منتشر شده است. با تونل SSH آزمایش کنید و برای دسترسی عمومی، دامنه و Reverse Proxy را کامل کنید.
برای بهروزرسانی فقط Image جدید بگیرم؟
ابتدا بکاپ و سازگاری نسخه را بررسی کنید. تگهای این نمونه ثابتِ تغییرناپذیر نیستند و ممکن است بهروزرسانی شوند؛ برای استقرار قابل تکرار، نسخه دقیق یا Digest آزمایششده را ثبت کنید. ارتقای عمده دیتابیس هم برنامه جدا میخواهد.
برای قدم بعد، راهنمای انتخاب RAM و CPU سرور مجازی را کنار مصرف واقعی سرویسها بررسی کنید. تعداد کانتینرها بهتنهایی معیار مناسبی برای انتخاب منابع نیست.



