ساخت محیط توسعه ایزوله با Docker Compose؛ راهنمای کامل پروژه‌های چندسرویسی

آموزش ساخت محیط توسعه ایزوله با Docker Compose برای پروژه‌های چندسرویسی و خلاص شدن از خطاهای ناسگاری سیستم.

🎧 خلاصه صوتی مقاله (پادکست ۲ دقیقه‌ای):

فرصت مطالعه ندارید؟ چکیده این مطلب را همین‌جا گوش دهید:

شایع‌ترین جمله‌ای که هر برنامه‌نویسی در طول دوران کاری خود می‌شنود و البته خودش هم بارها به زبان می‌آورد این است: «روی سیستم من به خوبی کار می‌کند!» اما وقتی همان کد روی سرور اصلی، سیستم همکار یا محیط تست اجرا می‌شود، ناگهان با خطاهای عجیب و غریبِ ناسگاری نسخه‌های پایگاه داده، پکیج‌های گم‌شده یا تداخل پورت‌ها روبه‌رو می‌شویم. این مشکل ریشه‌دار معمولاً ناشی از تفاوت‌های ظریف بین سیستم‌عامل‌ها و نسخه‌های ابزارهای نصب‌شده روی سیستم توسعه‌دهندگان است. راه‌حل قطعی این بحران، استفاده از کانتینرسازی و به طور خاص ابزار قدرتمند Docker Compose است تا بتوانید کل پشته نرم‌افزاری خود شامل وب‌اپلیکیشن، دیتابیس و سرویس‌های کش را تنها با یک دستور ساده و به شکلی کاملاً یکسان در هر سیستمی بالا بیاورید.

شاید در کنار توسعه نرم‌افزار، گاهی به ابزارهای کمکی دیگری مثل راهنمای جامع هوش مصنوعی Cody؛ دستیار هوشمند کدنویسی و تحلیل مخزن برای تحلیل کدهای خود نیاز داشته باشید، اما مدیریت زیرساخت و سرویس‌ها وظیفه اصلی داکر است. در این مقاله قصد داریم از صفر تا صد نحوه ساخت یک محیط توسعه ایزوله و حرفه‌ای را با استفاده از داکر کامپوز بررسی کنیم.

چرا محیط توسعه سنتی دیگر پاسخگو نیست؟

در روش‌های سنتی، برنامه‌نویس مجبور است پایگاه داده‌ای مثل PostgreSQL یا ابزار کشی مانند Redis را مستقیماً روی سیستم‌عامل خود (ویندوز، لینوکس یا مک) نصب کند. این کار چند مشکل بزرگ ایجاد می‌کند:

  • تداخل نسخه‌ها: اگر پروژه قدیمی شما به نسخه 14 پستgres نیاز داشته باشد و پروژه جدید نسخه 16 را بخواهید، نصب هم‌زمان آن‌ها دردسرآفرین است.
  • آلودگی سیستم: پاک کردن کامل سرویس‌ها و وابستگی‌های آن‌ها از روی سیستم‌عامل پس از پایان پروژه کار ساده‌ای نیست.
  • عدم تقارن با تولید: محیط پروداکشن (Production) معمولاً لینوکسی است، در حالی که توسعه روی ویندوز یا مک انجام می‌شود که این موضوع خطاهای پنهان به وجود می‌آورد.

داکر با ایزوله کردن هر سرویس داخل کانتینر مخصوص به خودش، تمامی این چالش‌ها را به طور ریشه‌ای حل می‌کند.

ساختار فایل docker-compose.yml برای یک وب‌پشته استاندارد

برای شروع کار، در پوشه اصلی پروژه خود فایلی به نام docker-compose.yml بسازید. در این مثال ما یک پشته شامل سه سرویس مجزا را پیاده‌سازی می‌کنیم: یک وب‌اپلیکیشن (بر پایه پایتون/فلاسک)، یک پایگاه داده PostgreSQL و یک سرویس کش Redis.

کد زیر را با دقت درون فایل docker-compose.yml قرار دهید:

version: '3.8'

services:
  web:
    build: .
    container_name: dev_web_app
    restart: always
    ports:
      - "5000:5000"
    volumes:
      - .:/app
    environment:
      - DATABASE_URL=postgresql://myuser:mypassword@db:5432/mydatabase
      - REDIS_HOST=redis
    depends_on:
      - db
      - redis

  db:
    image: postgres:15-alpine
    container_name: dev_postgres_db
    restart: always
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydatabase
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    container_name: dev_redis_cache
    restart: always
    ports:
      - "6379:6379"

volumes:
  pgdata:

بیایید این فایل پیکربندی را بخش به بخش تحلیل کنیم:

    بخش services: در این قسمت سرویس‌های مستقل برنامه تعریف می‌شوند. هر سرویس یک کانتینر مجزاست.
    سرویس web: از پوشه جاری (با دستور build: .) ایمیج داکر را می‌سازد. پورت 5000 سیستم شما را به پورت 5000 داخل کانتینر وصل می‌کند.
    بخش volumes در وب: خط .:/app یکی از حیاتی‌ترین بخش‌هاست؛ این دستور کدهای داخل سیستم شما را به صورت زنده (Live) به داخل پوشه /app در کانتینر متصل می‌کند تا با هر تغییر کد، نیازی به ساخت مجدد ایمیج نباشد.
    سرویس db و redis: از ایمیج‌های رسمی و سبک آلپاین (Alpine) استفاده می‌کنند که سرعت بالا و حجم بسیار کمی دارند.
    بخش volumes پایانی (pgdata): یک Volume اختصاصی برای دیتابیس تعریف می‌کند تا با خاموش یا حذف شدن کانتینر، اطلاعات ذخیره‌شده‌ی دیتابیس از بین نروند.

مدیریت هوشمند داده‌ها و شبکه‌بندی داخلی

یکی از بزرگ‌ترین مزیت‌های استفاده از Docker Compose، شبکه‌بندی خودکار (Automatic Networking) بین سرویس‌هاست. در تنظیمات بالا، سرویس وب برای اتصال به دیتابیس نیازی به دانستن آی‌پی سخت‌افزاری ندارد؛ کافی است در تنظیمات اتصال، نام سرویس یعنی کلمه db را به عنوان هاست وارد کنید (مانند postgresql://myuser:mypassword@db:5432/mydatabase). داکر خودش ترافیک را به شکل امن و داخلی بین کانتینرها هدایت می‌کند.

همچنین با استفاده از Volumeهای نام‌گذاری شده (Named Volumes)، خیالتان راحت است که اطلاعات ثبت شده در پایگاه داده با اجرای دستورات خاموشی حفظ خواهند شد. بدون این بخش، با هر بار اجرای دستور توقف، تمام اطلاعات دیتابیس پاک می‌شدند.

دستورات کاربردی برای اجرا، دیباگ و مدیریت

پس از آمادهسازی فایل تنظیمات، مدیریت کل این مجموعه بسیار لذت‌بخش و ساده است. دستورات زیر ابزارهای اصلی شما برای کار روزمره خواهند بود:

  1. اجرای سرویس‌ها در پس‌زمینه:
    دستور زیر ایمیج‌ها را دانلود، کانتینرها را ساخته و در حالت Background اجرا می‌کند:

    docker compose up -d
  2. مشاهده وضعیت زنده کانتینرها:
    برای اینکه ببینید کدام سرویس در حال اجراست و چه پورت‌هایی دارد:

    docker compose ps
  3. بررسی لاگ‌ها برای عیب‌یابی (Debug):
    اگر سرویسی بالا نیامد یا خطایی داد، با این دستور لاگ تمام سرویس‌ها را به صورت رنگی می‌بینید:

    docker compose logs -f
  4. متوقف کردن کامل سرویس‌ها:
    برای خاموش کردن محیط بدون اینکه داده‌های دیتابیس پاک شوند:

    docker compose stop
  5. پاکسازی کامل (کانتینرها و شبکه‌ها):
    اگر خواستید همه چیز را از نو شروع کنید (دقت کنید که Volumeها با این دستور پاک نمی‌شوند مگر اینکه سویچ -v را اضافه کنید):

    docker compose down
مشخصات فنی محیط نمونه Docker Compose

نام سرویسایمیج / پایهپورت پیش‌فرضوضعیت حفظ داده
وب‌اپلیکیشن (Web)سفارشی (Dockerfile محلی)5000مبتنی بر فایل سیستم محلی (Bind Mount)
پایگاه داده (DB)postgres:15-alpine5432حفظ شده در Volume اختصاصی (pgdata)
کش (Redis)redis:7-alpine6379موقت (In-Memory)

اشتباهات رایج و نکات پنهان در توسعه با داکر

با اینکه کار با داکر کامپوز بسیار روان است، رعایت چند نکته ظریف شما را از خطاهای آزاردهنده دور نگه می‌دارد:

    تداخل پورت‌ها: اگر روی هاست اصلی خودتان قبلاً یک پایگاه داده PostgreSQL روی پورت 5432 نصب کرده باشید، داکر نمی‌تواند پورت 5432 را به کانتینر اختصاص دهد. حتماً پیش از اجرا، سرویس‌های مشابه روی سیستم میزبان را متوقف کنید.
    ترتیب بالا آمدن سرویس‌ها: دستور depends_on فقط صبر می‌کند تا کانتینر دیتابیس استارت بخورد، اما تضمین نمی‌کند که موتور دیتابیس داخل کانتینر کاملاً آماده‌ی پذیرش کوئری شده باشد. برای کدهای اپلیکیشن خود حتماً مکانیزم تلاش مجدد (Retry Mechanism) برای اتصال به دیتابیس بنویسید.
    مدیریت فضای دیسک: ایمیج‌ها و کانتینرهای متوقف‌شده به مرور فضای دیسک را پر می‌کنند. هر چند وقت یک بار از دستور docker system prune برای پاکسازی فایل‌های اضافی استفاده کنید.

پرسش‌های متداول

آیا برای استفاده از Docker Compose نیازی به پرداخت هزینه یا لایسنس است؟

خیر، داکر کامپوز به صورت کاملاً متن‌باز و رایگان عرضه شده است و روی نسخه‌های دسکتاپ داکر (ویندوز و مک) و لینوکس به طور پیش‌فرض همراه با موتور اصلی نصب می‌شود.

چگونه می‌توانم کدهای داخل کانتینر را دیباگ کنم؟

شما می‌توانید با استفاده از دستور docker compose exec web bash مستقیماً وارد محیط ترمینال کانتینر در حال اجرای وب شوید و دستورات دلخواه خود را آنجا اجرا کنید.

اگر سیستم من رم یا پردازنده ضعیفی داشته باشد، اجرای هم‌زمان چند کانتینر کند می‌شود؟

اجرای هم‌زمان ایمیج‌های سبک مثل Alpine منابع بسیار کمی مصرف می‌کند و به مراتب سبک‌تر از نصب سنگین سرویس‌ها به صورت مستقیم روی سیستم‌عامل است.

جمع‌بندی

استفاده از Docker Compose برای مدیریت پروژه‌های چندسرویسی، خط بطلانی روی تمام مشکلات ناسگاری محیطی می‌کشد. با نوشتن یک فایل ساده تنظیمات، نه تنها توسعه فردی خود را ساختاریافته‌تر می‌کنید، بلکه شرایطی فراهم می‌شود که هر توسعه‌دهنده تازه‌واردی در تیم شما بتواند با اجرای تنها یک دستور docker compose up -d، در کمتر از دو دقیقه کل پشته نرم‌افزاری پروژه را آماده‌ی کدنویسی و تست کند. این رویکرد استاندارد طلایی توسعه نرم‌افزار مدرن است.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *