Docker Compose چیست؟ راهنمای راهاندازی چند سرویس روی سرور
Docker Compose چیست و چطور سرویسهای یک پروژه را روی سرور مدیریت میکند؟ با فایل compose.yaml، دستورهای اصلی، نکات امنیتی و اشتباههای رایج آشنا شوید.
یک وبسایت کوچک را روی سرور بالا آوردهاید. خود برنامه کار میکند، اما به پایگاه داده هم نیاز دارد. شاید فردا کش اضافه شود و هفته بعد بخواهید یک سرویس برای کارهای پسزمینه اجرا کنید. اگر قرار باشد تکتک این بخشها را با دستورهای پراکنده مدیریت کنید، بعد از چند تغییر، یادآوری تنظیمات از خود راهاندازی سختتر میشود. اینجاست که Docker Compose به کار میآید: راهی برای تعریف اجزای برنامه در یک فایل و کنترل آنها بهعنوان یک مجموعه.
Compose جادو نمیکند و جای مدیریت درست سرور را نمیگیرد. در عوض، پیچیدگی معمولِ اجرای چند کانتینر را قابلفهمتر میکند. در این راهنما میبینیم چه زمانی انتخاب مناسبی است، چگونه از یک فایل compose.yaml استفاده میشود و چه چیزهایی را پیش از استفاده در محیط واقعی باید بررسی کرد.
Docker Compose دقیقاً چیست؟
Docker بستری برای ساخت و اجرای کانتینرهاست. هر کانتینر معمولاً برنامه و وابستگیهای لازم برای اجرای آن را در محیطی جداگانه نگه میدارد. Docker Compose ابزاری است که چند سرویس کانتینری را در قالب یک پروژه تعریف میکند: تصویر یا روش ساخت آنها، شبکه ارتباطی، مسیرهای ذخیرهسازی، تنظیمات محیطی و شیوه راهاندازی.
تعریف پروژه معمولاً در فایلی به نام compose.yaml نوشته میشود. سپس با دستوری مثل docker compose up -d سرویسها ساخته یا اجرا میشوند. یعنی بهجای اینکه چند دستور طولانی docker run را در دفترچه نگه دارید، پیکربندی قابلبازبینی دارید که میتوان آن را در کنار کد پروژه نسخهبندی کرد؛ البته بدون قرار دادن رمزها در مخزن کد.
Compose با Dockerfile و Docker Engine چه تفاوتی دارد؟
این سه اسم اغلب کنار هم میآیند، اما کار یکسانی ندارند. Dockerfile دستور ساخت تصویر یک برنامه است؛ مثلاً برنامه را کپی میکند و وابستگیها را نصب میکند. Docker Engine کانتینر را اجرا و مدیریت میکند. Compose مشخص میکند این کانتینرها با چه تنظیماتی کنار یکدیگر بالا بیایند.
مثلاً ممکن است Dockerfile مربوط به برنامه Node.js باشد، درحالیکه Compose میگوید همان برنامه باید به سرویسی به نام cache وصل شود و پورت داخلی ۳۰۰۰ روی کدام آدرس سرور در دسترس قرار گیرد. پس Compose جای Dockerfile نیست؛ معمولاً آن را تکمیل میکند.
ابزار | وظیفه اصلی | سؤال کاربردی |
|---|---|---|
Dockerfile | ساخت تصویر | برنامه چگونه بستهبندی شود؟ |
Docker Engine | اجرای کانتینر | کانتینر روی میزبان چگونه کار کند؟ |
Docker Compose | تعریف مجموعه سرویسها | اجزای پروژه چطور کنار هم اجرا شوند؟ |
چه زمانی استفاده از Docker Compose منطقی است؟
برای پروژهای که فقط یک برنامه ساده دارد هم Compose مفید است؛ بهخصوص وقتی قرار است همان پیکربندی روی رایانه توسعهدهنده و سرور آزمایشی اجرا شود. ارزش اصلی آن وقتی معلوم میشود که سرویسهای وابسته اضافه میشوند.
فروشگاه اینترنتی را در نظر بگیرید که برنامه اصلی، پایگاه داده، کش و پردازشگر صف دارد. تیم فنی میخواهد بداند هر سرویس از کدام تصویر ساخته شده و دادههای پایدار کجا میمانند. Compose این نقشه را یکجا ثبت میکند. برای استقرار روی یک سرور نیز گزینهای عملی است، اما اگر به زمانبندی گسترده روی چند ماشین، مقیاسپذیری خودکار یا مدیریت پیچیده کلاستر نیاز دارید، باید ابزارهای مناسب آن معماری را جداگانه ارزیابی کنید.
آشنایی با پنج بخش مهم فایل compose.yaml
- services: نام و تنظیمات هر برنامه یا جزء مانند وباپلیکیشن و پایگاه داده.
- image یا build: استفاده از تصویر آماده یا ساخت تصویر از Dockerfile موجود.
- ports: نگاشت پورت میزبان به پورت کانتینر؛ این قسمت میتواند ناخواسته سرویسی را در اینترنت قابلدسترسی کند.
- volumes: نگهداری داده بیرون از چرخه عمر کانتینر، برای مثال فایلهای پایگاه داده.
- networks و environment: ارتباط سرویسها با یکدیگر و انتقال بخشی از تنظیمات اجرا.
یک نکته مهم: نام سرویسها در شبکه Compose بهعنوان نام قابلشناسایی استفاده میشود. بنابراین برنامه میتواند به جای حدس زدن IP کانتینر Redis، به نام cache متصل شود.
نمونه ساده Docker Compose برای یک برنامه و Redis
نمونه زیر برای آموزش است؛ فرض میکند در همین پوشه یک Dockerfile برای برنامهای دارید که روی پورت ۳۰۰۰ گوش میدهد و از متغیر REDIS_HOST استفاده میکند. پس بدون آماده بودن کد برنامه، این مثال یک وبسایت کامل و آماده اجرا نیست.
services: app: build: . ports: - "127.0.0.1:8080:3000" environment: REDIS_HOST: cache depends_on: cache: condition: service_healthy restart: unless-stopped cache: image: redis:7-alpine command: ["redis-server", "--appendonly", "yes"] volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 restart: unless-stoppedvolumes: redis-data:
در این مثال، سرویس app از کد محلی ساخته میشود. Redis از یک تصویر آماده استفاده میکند و دادههایش روی Volume نامدار نگه داشته میشود. اتصال پورت برنامه به 127.0.0.1 باعث میشود این پورت از طریق همان میزبان در دسترس باشد، نه همه واسطهای شبکه. برای دسترسی عمومی به وبسایت معمولاً به یک پراکسی معکوس و تنظیم صحیح HTTPS نیاز دارید.
گزینه depends_on با شرط service_healthy منتظر میماند بررسی سلامت Redis موفق شود؛ بااینحال، این گزینه تضمین نمیکند که سرویس در تمام طول عمر برنامه در دسترس بماند. خود برنامه باید قطع و وصل شدن وابستگیها را مدیریت کند.
آموزش اجرای پروژه؛ از بررسی فایل تا مشاهده لاگ
اول Docker و افزونه Compose را روی میزبان نصب کنید و نسخه را با docker compose version ببینید. سپس پوشه پروژه را باز کنید و فایل نمونه را به نام compose.yaml قرار دهید. پیش از اجرا، بهتر است ساختار نهایی پیکربندی را بررسی کنید:
docker compose config
اگر خروجی معتبر بود، سرویسها را در پسزمینه راهاندازی کنید:
docker compose up -d --build
برای دیدن وضعیت و لاگ برنامه از این دستورها استفاده کنید:
docker compose psdocker compose logs -f app
وقتی فقط کد سرویس app را تغییر دادهاید، ممکن است بخواهید همان بخش را دوباره بسازید و اجرا کنید. اما پیش از هر بازاستقرار، اثر آن بر درخواستهای جاری و اتصالها را بسنجید؛ همه سرویسها قطع و وصل شدن کوتاه را به یک شکل تحمل نمیکنند.
تفاوت stop، down و حذف دادهها
یکی از اشتباههای پرهزینه، اجرای دستور بدون توجه به Volumeهاست. docker compose stop کانتینرهای پروژه را متوقف میکند. docker compose down کانتینرها و شبکههای ساختهشده توسط پروژه را جمع میکند، اما در حالت معمول Volumeهای نامدار را حذف نمیکند. گزینه -v میتواند Volumeها را هم پاک کند؛ اگر داده واقعی دارید، پیش از استفاده از آن دقیقاً بدانید چه چیزی از دست خواهد رفت.
Volume جای نسخه پشتیبان نیست. اگر پایگاه داده خراب شود، حذف ناخواسته رخ دهد یا خود میزبان آسیب ببیند، داشتن فایلهای پایدار بهتنهایی کافی نخواهد بود. پشتیبانگیری قابلبازیابی، نگهداری نسخه خارج از سرور و آزمایش دورهای بازیابی را از ابتدا در برنامه بگذارید.
تنظیمات محیطی و رمزها را چگونه نگه داریم؟
متغیرهای محیطی برای آدرس سرویسها و تنظیمات غیرمحرمانه مناسباند، اما گذاشتن رمز پایگاه داده یا کلید API در متن فایل Compose و مخزن Git کار درستی نیست. فایل .env هم بهخودیخود گاوصندوق امن نیست؛ اگر محتوا محرمانه است باید دسترسی، نگهداری و چرخه تعویض آن کنترل شود. در محیطهای حساس از روش مدیریت اسرار متناسب با زیرساخت استفاده کنید.
برای استقرار واقعی معمولاً یک فایل جدا مثل compose.production.yaml در نظر گرفته میشود تا سیاست راهاندازی مجدد، پورتها و تنظیمات مخصوص تولید با محیط توسعه قاطی نشوند. مشخص بودن نسخه تصویرها، محدود کردن دسترسی کانتینرها و بازبینی تغییرات قبل از استقرار نیز اهمیت دارد. استفاده بیحساب از برچسب latest میتواند نتیجه استقرار بعدی را غیرقابلپیشبینی کند.
اشتباههای رایج در استقرار با Compose
باز گذاشتن پورت پایگاه داده
وقتی سرویس پایگاه داده فقط برای برنامه داخلی لازم است، معمولاً نیازی نیست پورت آن روی اینترنت منتشر شود. ارتباط سرویسهای یک پروژه از طریق شبکه داخلی Compose انجام میشود. باز بودن غیرضروری پورتها سطح حمله را افزایش میدهد.
تصور اینکه اجرای کانتینر یعنی سالم بودن برنامه
وضعیت Up بهتنهایی نمیگوید سرویس آماده پاسخگویی درست به کاربر است. بررسی سلامت واقعی، پایش منابع و هشدار برای خطاهای مهم را جداگانه طراحی کنید. لاگ نیز باید چنان تنظیم شود که هم قابلبررسی باشد و هم بدون محدودیت، فضای دیسک را پر نکند.
تغییر مستقیم فایل داخل کانتینر
ممکن است امروز یک فایل را دستی اصلاح کنید و مشکل حل شود، اما با ساخت دوباره کانتینر تغییر از بین برود. مسیر پایدار این است که اصلاحات لازم در کد، Dockerfile یا پیکربندی تعریفشده ثبت شود؛ نه فقط در وضعیت موقت یک کانتینر.
Docker Compose یا Kubernetes؟
این دو را فقط با عبارت «کوچک و بزرگ» مقایسه نکنید. Compose برای تعریف و اداره مجموعهای از سرویسها، بهویژه روی یک میزبان، ساده و خوشدست است. Kubernetes برای هماهنگسازی کانتینرها در زیرساخت پیچیدهتر، زمانبندی، سیاستهای استقرار و مدیریت وضعیت مطلوب طراحی شده، اما هزینه یادگیری و عملیات بیشتری دارد.
اگر تیم کوچکی دارید و سرویسها روی یک سرور مشخص با نیازهای قابلکنترل کار میکنند، Compose میتواند انتخاب معقولی باشد. زمانی به گزینههای پیشرفتهتر فکر کنید که نیاز واقعی مانند چندمیزبانی، تحمل خرابی گسترده یا مقیاسپذیری عملیاتی دارید، نه صرفاً بهخاطر مشهور بودن یک ابزار.
پرسشهای متداول درباره Docker Compose
آیا Compose فقط برای توسعه است؟
خیر. برای استقرار روی یک سرور نیز کاربرد دارد. البته تنظیمات تولید، پشتیبانگیری، پایش و امنیت باید جداگانه طراحی شوند.
آیا با حذف کانتینر، اطلاعات پایگاه داده پاک میشود؟
به محل ذخیره داده بستگی دارد. داده داخل لایه قابلنوشتن کانتینر ممکن است از بین برود؛ Volume نامدار برای پایدارسازی داده به کار میرود، اما باز هم نیازمند پشتیبان است.
آیا Docker Compose خودش SSL و دامنه راه میاندازد؟
خیر. میتوانید پراکسی معکوس و مدیریت گواهی را به پروژه اضافه کنید، ولی پیکربندی درست دامنه و HTTPS مسئولیت شماست.
آیا لازم است حتماً پایگاه داده داخل کانتینر باشد؟
نه. برنامه داخل Compose میتواند به یک پایگاه داده مدیریتشده بیرونی نیز وصل شود. انتخاب به نیاز امنیتی، بودجه، نگهداری و الگوی ترافیک بستگی دارد.
جمعبندی؛ از سادگی شروع کنید، اما زیرساخت را جدی بگیرید
Docker Compose زمانی بیشترین فایده را دارد که اجرای برنامه از چند دستور پراکنده به یک پیکربندی قابلفهم تبدیل شود. برای آزمایش، توسعه تیمی و تعداد زیادی از استقرارهای تکسروری راهحل مناسبی است. فقط یادتان باشد نسخه پشتیبان، مدیریت رمزها و مانیتورینگ جزو کارهایی نیستند که با نوشتن یک فایل YAML خودبهخود انجام شوند. یک پروژه کوچک با تنظیمات روشن، معمولاً بهتر از زیرساخت بزرگی است که کسی از جزئیاتش خبر ندارد.
نظرات و گفتوگو
نظرها پس از تایید مدیر منتشر میشوند. پاسخهای رسمی مدیر با نشان مشخص نمایش داده میشوند.