آموزش Docker Compose: شروعی قدرتمند برای مدیریت برنامه‌های کانتینری

فهرست مطالب

آموزش Docker Compose: شروعی قدرتمند برای مدیریت برنامه‌های کانتینری

در دنیای مدرن توسعه نرم‌افزار، کانتینرها انقلابی در نحوه ساخت، بسته‌بندی و استقرار برنامه‌ها ایجاد کرده‌اند. Docker به عنوان پیشرو این انقلاب، به توسعه‌دهندگان این امکان را می‌دهد که برنامه‌های خود و تمام وابستگی‌هایشان را در واحدهای ایزوله و قابل حمل بسته‌بندی کنند. اما چالش واقعی زمانی آغاز می‌شود که یک برنامه شامل چندین کانتینر مجزا باشد که هر کدام نقش خاصی را ایفا می‌کنند؛ مثلاً یک کانتینر برای وب‌سرور، یک کانتینر برای پایگاه داده، و دیگری برای کش. مدیریت دستی این کانتینرها، لینک کردن آن‌ها، و اطمینان از راه‌اندازی صحیحشان می‌تواند بسیار وقت‌گیر و مستعد خطا باشد. اینجا است که Docker Compose وارد عمل می‌شود.

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

این مقاله به عنوان یک راهنمای جامع و تخصصی، شما را از مفاهیم اولیه Docker Compose تا جزئیات پیشرفته‌تر آن همراهی می‌کند. هدف ما این است که شما را با ابزاری مجهز کنیم که نه تنها پیچیدگی مدیریت کانتینرهای چندگانه را کاهش می‌دهد، بلکه به شما کمک می‌کند تا جریان کاری (workflow) توسعه خود را بهینه‌سازی کرده و برنامه‌های کانتینری خود را با اطمینان و سهولت بیشتری مدیریت کنید. آماده‌اید تا قدرت واقعی Docker Compose را کشف کنید؟ بیایید شروع کنیم!

مقدمه‌ای بر Docker Compose و ضرورت آن در دنیای کانتینرها

همانطور که می‌دانید، Docker یک پلتفرم متن‌باز است که توسعه‌دهندگان را قادر می‌سازد تا برنامه‌ها را به همراه تمام وابستگی‌هایشان در کانتینرهای سبک و قابل حمل بسته‌بندی کنند. این کانتینرها ایزوله هستند و تضمین می‌کنند که برنامه در هر محیطی، به همان شکلی که در محیط توسعه کار می‌کند، عمل خواهد کرد. با این حال، در سناریوهای واقعی، اکثر برنامه‌های کاربردی مدرن، به ویژه آن‌هایی که معماری میکروسرویس‌گرا دارند، تنها از یک کانتینر تشکیل نشده‌اند. آن‌ها معمولاً مجموعه‌ای از سرویس‌های مرتبط هستند که هر کدام در کانتینر خود اجرا می‌شوند و با یکدیگر تعامل دارند.

به عنوان مثال، فرض کنید یک برنامه وب دارید که از یک فرانت‌اند (مثلاً Nginx برای سرویس‌دهی به فایل‌های استاتیک)، یک بک‌اند (مثلاً یک API مبتنی بر Python Flask یا Node.js)، و یک پایگاه داده (مانند PostgreSQL یا MongoDB) تشکیل شده است. در این سناریو، شما حداقل سه کانتینر مجزا خواهید داشت. مدیریت دستی این سه کانتینر با دستورات Docker به صورت جداگانه (مثلاً docker run برای هر کانتینر، اطمینان از اتصال صحیح آن‌ها به یکدیگر، و مدیریت وابستگی‌های راه‌اندازی) می‌تواند بسیار پیچیده و مستعد خطا باشد. اینجاست که Docker Compose به عنوان یک راه‌حل حیاتی و ضروری مطرح می‌شود.

Docker Compose چیست؟

Docker Compose ابزاری است که به شما امکان می‌دهد برنامه‌های چندکانتینری را تعریف و اجرا کنید. این ابزار از یک فایل پیکربندی به نام docker-compose.yml استفاده می‌کند که در آن تمام سرویس‌های (کانتینرهای) برنامه شما، شبکه‌هایی که با یکدیگر ارتباط برقرار می‌کنند، و حجم‌های (volumes) داده‌ای که برای پایداری داده‌ها استفاده می‌شوند، به صورت declarative تعریف می‌شوند. به جای نوشتن ده‌ها دستور docker run با فلگ‌های مختلف، شما یک بار تمام پیکربندی را در این فایل YAML می‌نویسید و سپس با یک دستور ساده مانند docker-compose up، Docker Compose مسئولیت راه‌اندازی و مدیریت کل پشته برنامه شما را بر عهده می‌گیرد.

چرا Docker Compose ضروری است؟

ضرورت Docker Compose در محیط‌های توسعه و تست و حتی در مراحل اولیه استقرار برنامه‌های کوچک تا متوسط، از جنبه‌های مختلفی قابل مشاهده است:

  1. ساده‌سازی مدیریت برنامه‌های چندکانتینری: به جای راه‌اندازی و مدیریت هر کانتینر به صورت جداگانه، Docker Compose یک راهکار یکپارچه برای مدیریت کل برنامه ارائه می‌دهد. این موضوع باعث صرفه‌جویی در زمان و کاهش پیچیدگی می‌شود.
  2. تکرارپذیری (Reproducibility): فایل docker-compose.yml یک تعریف دقیق و قابل تکرار از محیط برنامه شما فراهم می‌کند. هر توسعه‌دهنده‌ای در تیم شما یا هر سرور CI/CD می‌تواند با استفاده از این فایل، دقیقاً همان محیط را بازسازی کند. این امر به کاهش مشکلات “روی دستگاه من کار می‌کرد!” کمک می‌کند.
  3. ایزوله‌سازی محیط‌ها: Compose به شما امکان می‌دهد تا شبکه‌های سفارشی برای سرویس‌های خود تعریف کنید، که این امر به ایزوله‌سازی بهتر و کنترل دقیق‌تر بر ارتباطات بین کانتینرها کمک می‌کند.
  4. پیکربندی ساده: فایل YAML خوانایی بالایی دارد و به شما اجازه می‌دهد تا تمام جنبه‌های سرویس‌های خود (مانند پورت‌ها، حجم‌ها، متغیرهای محیطی، وابستگی‌ها و غیره) را به راحتی پیکربندی کنید.
  5. مدیریت چرخه حیات کامل: با Compose می‌توانید نه تنها برنامه را راه‌اندازی کنید، بلکه آن را متوقف، بازسازی، مقیاس‌بندی و حذف کنید، همه با دستورات ساده و یکپارچه.
  6. مناسب برای توسعه و تست: Docker Compose به طور خاص برای ساده‌سازی محیط‌های توسعه و تست بسیار مناسب است. توسعه‌دهندگان می‌توانند به سرعت یک کپی محلی از محیط تولید را راه‌اندازی کنند تا کد خود را آزمایش کنند.

به طور خلاصه، Docker Compose یک لایه انتزاعی قدرتمند بر روی دستورات پایه Docker اضافه می‌کند تا مدیریت برنامه‌های کانتینری پیچیده را به یک فرآیند ساده و کارآمد تبدیل کند. این ابزار به توسعه‌دهندگان و تیم‌های DevOps این امکان را می‌دهد که با اطمینان بیشتری به سوی معماری‌های مدرن نرم‌افزار حرکت کنند و از مزایای کامل کانتینرسازی بهره‌مند شوند.

نصب و راه‌اندازی Docker Compose: آماده‌سازی محیط

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

پیش‌نیازها

  • Docker Engine: Docker Engine نسخه ۱.۱۰.۰ یا بالاتر.

نصب Docker Compose در Linux

در سیستم‌عامل‌های مبتنی بر Linux، Docker Compose به صورت یک باینری مستقل منتشر می‌شود که می‌توانید آن را دانلود کرده و در مسیر PATH سیستم خود قرار دهید. این روش توصیه شده برای نصب Docker Compose است:

  1. دانلود Docker Compose:

    ابتدا، آخرین نسخه پایدار Docker Compose را از مخزن GitHub آن دانلود کنید. می‌توانید نسخه فعلی را در صفحه releases پیدا کنید. برای مثال، برای نسخه 2.24.5 (شما باید آخرین نسخه پایدار را جایگزین کنید):

    sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

    نکته: $(uname -s) سیستم عامل (Linux) و $(uname -m) معماری پردازنده (x86_64، armhf، aarch64 و غیره) را تشخیص می‌دهد.

  2. اعمال مجوزهای اجرایی:

    پس از دانلود، باید مجوزهای اجرایی را به فایل باینری بدهید:

    sudo chmod +x /usr/local/bin/docker-compose
  3. بررسی نصب:

    برای اطمینان از اینکه Docker Compose به درستی نصب شده است، می‌توانید شماره نسخه آن را بررسی کنید:

    docker-compose --version

    خروجی باید چیزی شبیه به این باشد:

    Docker Compose version v2.24.5

نکته برای کاربران Docker Desktop در Linux: اگر از Docker Desktop برای Linux استفاده می‌کنید، Docker Compose (نسخه V2) به صورت پیش‌فرض همراه آن نصب شده است و نیازی به نصب جداگانه ندارید. می‌توانید با دستور docker compose --version آن را بررسی کنید.

نصب Docker Compose در macOS

برای کاربران macOS، ساده‌ترین و توصیه‌شده‌ترین راه برای نصب Docker Compose، نصب Docker Desktop for Mac است. Docker Desktop شامل Docker Engine، Docker CLI client، Docker Compose، Kubernetes و Kinematic می‌شود. Docker Compose (نسخه V2) به صورت پیش‌فرض در Docker Desktop گنجانده شده است.

  1. دانلود و نصب Docker Desktop:

    به وب‌سایت رسمی Docker (https://docs.docker.com/desktop/install/mac-install/) مراجعه کرده و Docker Desktop for Mac را دانلود و نصب کنید. این فرآیند معمولاً شامل کشیدن آیکون Docker به پوشه Applications است.

  2. اجرای Docker Desktop:

    پس از نصب، Docker Desktop را اجرا کنید. آیکون Docker در نوار منو ظاهر می‌شود و نشان می‌دهد که Docker Engine در حال اجرا است.

  3. بررسی نصب:

    یک ترمینال باز کنید و دستور زیر را اجرا کنید:

    docker compose --version

    خروجی باید شماره نسخه Docker Compose را نمایش دهد. توجه داشته باشید که با Docker Desktop، از docker compose (بدون خط تیره) استفاده می‌کنید که نسخه V2 است.

نصب Docker Compose در Windows

مانند macOS، بهترین راه برای نصب Docker Compose در Windows، نصب Docker Desktop for Windows است. Docker Desktop for Windows شامل Docker Engine و Docker Compose (نسخه V2) می‌شود.

  1. دانلود و نصب Docker Desktop:

    به وب‌سایت رسمی Docker (https://docs.docker.com/desktop/install/windows-install/) مراجعه کرده و Docker Desktop for Windows را دانلود و نصب کنید. فرآیند نصب به صورت یک ویزارد است.

  2. اجرای Docker Desktop:

    پس از نصب، Docker Desktop را اجرا کنید. آیکون آن در نوار وظیفه (System Tray) ظاهر می‌شود و نشان می‌دهد که Docker Engine در حال اجرا است.

  3. بررسی نصب:

    یک Command Prompt یا PowerShell باز کنید و دستور زیر را اجرا کنید:

    docker compose --version

    خروجی باید شماره نسخه Docker Compose را نمایش دهد. باز هم، با Docker Desktop، از docker compose (بدون خط تیره) استفاده می‌کنید.

تفاوت Docker Compose (V1) و docker compose (V2)

ممکن است در منابع مختلف با دستور docker-compose (با خط تیره) و docker compose (بدون خط تیره) مواجه شوید. تفاوت اصلی به نسخه‌های Docker Compose برمی‌گردد:

  • Docker Compose V1 (docker-compose): این نسخه اصلی و قدیمی‌تر Docker Compose است که به صورت یک باینری پایتون نصب می‌شد.
  • Docker Compose V2 (docker compose): این نسخه جدیدتر و بازنویسی شده Docker Compose است که به زبان Go نوشته شده است. این نسخه به عنوان یک پلاگین برای Docker CLI ادغام شده است، به این معنی که شما آن را با docker compose (به عنوان یک زیردستور Docker) اجرا می‌کنید، نه به عنوان یک دستور مستقل. Docker Desktop به صورت پیش‌فرض از V2 استفاده می‌کند. توصیه می‌شود همیشه از V2 استفاده کنید زیرا بهبودهای عملکردی و ادغام بهتری با Docker CLI دارد.

در این آموزش، ما عمدتاً بر روی docker compose (نسخه V2) تمرکز خواهیم کرد، اما اکثر پیکربندی‌ها در فایل docker-compose.yml بین هر دو نسخه سازگار هستند.

پس از اتمام مراحل نصب و تأیید عملکرد Docker Compose، محیط شما آماده است تا شروع به تعریف و مدیریت برنامه‌های چندکانتینری خود کنید. در بخش بعدی، به قلب Docker Compose، یعنی فایل docker-compose.yml خواهیم پرداخت.

آشنایی با ساختار فایل docker-compose.yml: قلب تپنده مدیریت کانتینرها

فایل docker-compose.yml (یا docker-compose.yaml) هسته اصلی هر پروژه Docker Compose است. این فایل با فرمت YAML نوشته می‌شود و تمام پیکربندی‌های لازم برای تعریف سرویس‌ها، شبکه‌ها و حجم‌های داده‌ای برنامه چندکانتینری شما را در خود جای می‌دهد. درک صحیح ساختار این فایل برای استفاده مؤثر از Docker Compose بسیار حیاتی است.

ساختار کلی فایل YAML

YAML یک زبان سریال‌سازی داده‌ها است که به دلیل خوانایی بالا و سادگی‌اش، به طور گسترده در فایل‌های پیکربندی استفاده می‌شود. نکات کلیدی YAML:

  • تو رفتگی (Indentation): ساختار YAML بر پایه تو رفتگی با فاصله‌ها (spaces) استوار است. تب‌ها (tabs) مجاز نیستند و منجر به خطا می‌شوند. تو رفتگی‌ها سلسله مراتب عناصر را نشان می‌دهند.
  • جفت‌های کلید-مقدار (Key-Value Pairs): اکثر داده‌ها به صورت کلید: مقدار تعریف می‌شوند.
  • لیست‌ها (Lists): آیتم‌های یک لیست با خط تیره (-) در ابتدای هر آیتم و یک فاصله مشخص می‌شوند.

یک مثال ساده از ساختار YAML:

version: "3.8"
services:
  web:
    image: nginx
    ports:
      - "80:80"
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: mysecretpassword

کلیدهای سطح بالای (Top-Level Keys) فایل docker-compose.yml

فایل docker-compose.yml معمولاً از چند کلید سطح بالا تشکیل شده است که هر کدام بخش خاصی از پیکربندی را مدیریت می‌کنند:

  1. version:

    این کلید نسخه فرمت فایل Compose را مشخص می‌کند. بسیار مهم است که نسخه صحیح را انتخاب کنید، زیرا هر نسخه ویژگی‌ها و سینتکس‌های خاص خود را دارد. توصیه می‌شود همیشه از جدیدترین نسخه پایدار (مثلاً "3.8" یا "3.9") استفاده کنید که قابلیت‌های بیشتری را ارائه می‌دهد.

    version: "3.8"
  2. services:

    این بخش اصلی‌ترین قسمت فایل Compose است که در آن تمام سرویس‌های (کانتینرهای) تشکیل‌دهنده برنامه شما تعریف می‌شوند. هر سرویس یک نام منحصر به فرد دارد که به عنوان نام هاست (hostname) آن کانتینر در شبکه داخلی Compose نیز عمل می‌کند.

    services:
      web:
        # پیکربندی سرویس web
      db:
        # پیکربندی سرویس db
    
  3. networks:

    این بخش برای تعریف شبکه‌های سفارشی است که سرویس‌های شما می‌توانند برای ارتباط با یکدیگر از آن‌ها استفاده کنند. اگر این بخش را تعریف نکنید، Compose یک شبکه پیش‌فرض برای پروژه شما ایجاد می‌کند.

    networks:
      app_net:
        driver: bridge
    
  4. volumes:

    این بخش برای تعریف حجم‌های داده‌ای (named volumes) است که به شما امکان می‌دهد داده‌ها را بین اجراهای کانتینرها پایدار نگه دارید. این حجم‌ها از چرخه حیات کانتینرها مستقل هستند.

    volumes:
      db_data:
    

پیکربندی سرویس‌ها (services) – جزئیات

هر سرویس زیر کلید services می‌تواند شامل چندین گزینه پیکربندی باشد:

  • image:

    مشخص می‌کند که کانتینر از کدام ایمیج Docker ساخته شود. این می‌تواند یک ایمیج از Docker Hub باشد (مثلاً nginx، postgres:16) یا یک ایمیج که شما قبلاً ساخته‌اید.

    image: nginx:latest
  • build:

    به جای استفاده از یک ایمیج موجود، می‌توانید Docker Compose را وادار کنید که ایمیج را از یک Dockerfile بسازد. این گزینه می‌تواند یک مسیر به دایرکتوری حاوی Dockerfile باشد، یا یک شیء که شامل context (مسیر Dockerfile) و dockerfile (نام Dockerfile در صورت غیرپیش‌فرض بودن) باشد.

    build: ./app_frontend
    build:
      context: .
      dockerfile: Dockerfile.dev
    
  • ports:

    نقشه‌برداری پورت‌ها بین هاست و کانتینر. فرمت "HOST_PORT:CONTAINER_PORT" است.

    ports:
      - "80:80"
      - "443:443"
  • volumes:

    نقشه‌برداری حجم‌های داده‌ای. می‌تواند شامل bind mounts ("HOST_PATH:CONTAINER_PATH") یا named volumes ("VOLUME_NAME:CONTAINER_PATH") باشد.

    volumes:
      - ./app_code:/app
      - db_data:/var/lib/postgresql/data
    
  • environment:

    تنظیم متغیرهای محیطی درون کانتینر. می‌تواند یک لیست از "KEY=VALUE" یا یک دیکشنری باشد.

    environment:
      - POSTGRES_PASSWORD=mysecretpassword
      - DATABASE_NAME=mydatabase
    

    یا

    environment:
      POSTGRES_PASSWORD: mysecretpassword
      DATABASE_NAME: mydatabase
    
  • env_file:

    بارگذاری متغیرهای محیطی از یک فایل. هر خط در فایل باید به فرمت KEY=VALUE باشد.

    env_file:
      - .env
      - .env.production
    
  • depends_on:

    تعیین وابستگی بین سرویس‌ها. Compose اطمینان حاصل می‌کند که سرویس‌های لیست شده قبل از راه‌اندازی این سرویس، راه‌اندازی شوند. این فقط ترتیب راه‌اندازی را تضمین می‌کند، نه اینکه سرویس‌های وابسته آماده (ready) باشند.

    depends_on:
      - db
      - redis
    
  • networks:

    تعیین شبکه‌هایی که کانتینر به آن‌ها متصل می‌شود. اگر شبکه‌ای تعریف نشده باشد، به شبکه پیش‌فرض پروژه متصل می‌شود.

    networks:
      - app_net
      - backend_net
    
  • container_name:

    نام مشخصی برای کانتینر تعیین می‌کند. در صورت عدم تعریف، Compose یک نام به صورت projectname_servicename_N ایجاد می‌کند.

    container_name: my_web_app
  • restart:

    سیاست بازراه‌اندازی کانتینر در صورت توقف. گزینه‌ها شامل no (پیش‌فرض)، always، on-failure و unless-stopped هستند.

    restart: always
  • command:

    نادیده گرفتن دستور پیش‌فرض (ENTRYPOINT/CMD) ایمیج و اجرای یک دستور خاص هنگام راه‌اندازی کانتینر.

    command: ["python", "app.py"]
  • entrypoint:

    نادیده گرفتن entrypoint پیش‌فرض ایمیج. این دستور همیشه اجرا می‌شود، حتی اگر command تعریف شده باشد.

    entrypoint: ["/usr/bin/supervisord", "-n"]
  • expose:

    اعلام پورت‌هایی که کانتینر در شبکه داخلی خود در دسترس قرار می‌دهد، بدون اینکه آن‌ها را به پورت‌های هاست نقشه‌برداری کند. این پورت‌ها فقط برای سرویس‌های دیگر در شبکه Compose قابل دسترسی هستند.

    expose:
      - "8000"
      - "8001"
    
  • healthcheck:

    تعریف یک بررسی سلامت (health check) برای اطمینان از اینکه سرویس به درستی کار می‌کند، نه فقط اینکه اجرا می‌شود. این می‌تواند برای depends_on یا ابزارهای اورکستراسیون مفید باشد.

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    
  • labels:

    اضافه کردن متادیتای سفارشی به کانتینر به شکل جفت‌های کلید-مقدار.

    labels:
      com.example.description: "My web application"
    

درک این پیکربندی‌ها به شما امکان می‌دهد تا برنامه‌های کانتینری خود را با جزئیات کامل و دقت بالا تعریف کنید. در بخش بعدی، این دانش را با ساخت یک پروژه عملی به کار خواهیم گرفت.

ساخت اولین پروژه چند کانتینری با Docker Compose: یک مثال عملی

برای درک عمیق‌تر مفاهیم Docker Compose، بهترین راه، ساخت یک پروژه عملی است. در این مثال، ما یک برنامه وب ساده شامل سه سرویس راه‌اندازی خواهیم کرد:

  • وب‌سرویس (Flask): یک برنامه Python Flask که محتوای ساده‌ای را نمایش می‌دهد.
  • پایگاه داده (PostgreSQL): یک پایگاه داده برای ذخیره‌سازی داده‌ها (اگرچه در این مثال Flask فقط اطلاعاتی را از محیط می‌خواند، اما ساختار پایگاه داده را نشان می‌دهد).
  • Nginx: به عنوان یک reverse proxy در جلوی وب‌سرویس Flask، درخواست‌ها را از پورت 80 به پورت داخلی Flask هدایت می‌کند.

ساختار دایرکتوری پروژه

ابتدا، یک دایرکتوری برای پروژه خود ایجاد کنید:

mkdir my_compose_app
cd my_compose_app

سپس، ساختار فایل‌های لازم را ایجاد می‌کنیم:

my_compose_app/
├── docker-compose.yml
├── app/
│   ├── Dockerfile
│   ├── app.py
│   └── requirements.txt
└── nginx/
    └── nginx.conf

فایل‌های پروژه

۱. app/app.py (برنامه Flask)

این فایل یک برنامه Flask بسیار ساده است:

# app/app.py
from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    db_host = os.environ.get('DB_HOST', 'localhost')
    db_port = os.environ.get('DB_PORT', '5432')
    db_user = os.environ.get('DB_USER', 'user')
    db_name = os.environ.get('DB_NAME', 'database')
    
    return f"Hello from Flask app! Connected to DB at {db_host}:{db_port} with user {db_user} for database {db_name}."

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

۲. app/requirements.txt (وابستگی‌های Flask)

این فایل وابستگی‌های Python را برای برنامه Flask مشخص می‌کند:

# app/requirements.txt
Flask==2.3.3

۳. app/Dockerfile (برای ساخت ایمیج Flask)

این Dockerfile ایمیج Flask ما را می‌سازد:

# app/Dockerfile
FROM python:3.9-slim-buster

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["python", "app.py"]

۴. nginx/nginx.conf (پیکربندی Nginx)

این فایل Nginx را پیکربندی می‌کند تا درخواست‌ها را به سرویس Flask ما ارسال کند:

# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream flask_app {
        server flask_app_service:5000; # نام سرویس flask_app_service در docker-compose.yml
    }

    server {
        listen 80;

        location / {
            proxy_pass http://flask_app;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

نکته مهم: در بخش upstream flask_app، نام سرور را flask_app_service قرار داده‌ایم. این نام باید با نام سرویس Flask در فایل docker-compose.yml مطابقت داشته باشد.

۵. docker-compose.yml (فایل پیکربندی اصلی)

این فایل سه سرویس ما (Flask، PostgreSQL، Nginx) را تعریف می‌کند:

# docker-compose.yml
version: "3.8"

services:
  nginx_service:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - flask_app_service
    networks:
      - app_network

  flask_app_service:
    build: ./app
    environment:
      DB_HOST: db_service
      DB_PORT: 5432
      DB_USER: myuser
      DB_NAME: mydatabase
    expose:
      - "5000" # پورت داخلی flask برای nginx
    networks:
      - app_network
    depends_on:
      - db_service

  db_service:
    image: postgres:16
    environment:
      POSTGRES_DB: mydatabase
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mysecretpassword
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - app_network

networks:
  app_network:
    driver: bridge

volumes:
  db_data:

توضیحات فایل docker-compose.yml:

  • version: "3.8": از نسخه 3.8 فرمت Compose استفاده می‌کند.
  • services:
    • nginx_service:
      • image: nginx:latest: از آخرین ایمیج Nginx استفاده می‌کند.
      • ports: - "80:80": پورت 80 هاست را به پورت 80 کانتینر Nginx نقشه‌برداری می‌کند.
      • volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro: فایل پیکربندی Nginx محلی ما را به داخل کانتینر (فقط خواندنی: ro) mount می‌کند.
      • depends_on: - flask_app_service: تضمین می‌کند که flask_app_service قبل از nginx_service راه‌اندازی شود.
      • networks: - app_network: به شبکه app_network متصل می‌شود.
    • flask_app_service:
      • build: ./app: ایمیج این سرویس را از Dockerfile موجود در دایرکتوری ./app می‌سازد.
      • environment: متغیرهای محیطی را برای برنامه Flask تنظیم می‌کند. این متغیرها توسط app.py خوانده می‌شوند.
      • expose: - "5000": پورت 5000 (پورت پیش‌فرض Flask) را به صورت داخلی در شبکه Compose برای سرویس‌های دیگر (مانند Nginx) در دسترس قرار می‌دهد، اما آن را به هاست نقشه‌برداری نمی‌کند.
      • networks: - app_network: به شبکه app_network متصل می‌شود.
      • depends_on: - db_service: تضمین می‌کند که db_service قبل از flask_app_service راه‌اندازی شود.
    • db_service:
      • image: postgres:16: از ایمیج PostgreSQL نسخه 16 استفاده می‌کند.
      • environment: متغیرهای محیطی را برای پیکربندی PostgreSQL تنظیم می‌کند.
      • volumes: - db_data:/var/lib/postgresql/data: یک named volume به نام db_data را به مسیر داده‌های PostgreSQL در کانتینر mount می‌کند تا داده‌ها پایدار بمانند.
      • networks: - app_network: به شبکه app_network متصل می‌شود.
  • networks:
    • app_network: driver: bridge: یک شبکه سفارشی از نوع bridge به نام app_network ایجاد می‌کند. این باعث می‌شود سرویس‌ها بتوانند با نام یکدیگر (مثلاً db_service، flask_app_service) با هم ارتباط برقرار کنند.
  • volumes:
    • db_data:: یک named volume به نام db_data تعریف می‌کند که توسط سرویس db_service برای ذخیره داده‌های پایگاه داده استفاده می‌شود.

اجرای پروژه

حالا که تمام فایل‌ها را ایجاد کرده‌اید، می‌توانید برنامه خود را با Docker Compose راه‌اندازی کنید. به دایرکتوری اصلی پروژه (my_compose_app) بروید و دستور زیر را اجرا کنید:

docker compose up

این دستور تمام ایمیج‌های مورد نیاز را دانلود می‌کند (یا می‌سازد)، کانتینرها را راه‌اندازی می‌کند و لاگ‌های آن‌ها را در ترمینال نمایش می‌دهد. برای اجرای کانتینرها در پس‌زمینه (detached mode)، از فلگ -d استفاده کنید:

docker compose up -d

پس از اجرای دستور، می‌توانید مرورگر خود را باز کرده و به آدرس http://localhost (یا http://your_server_ip) بروید. باید پیامی مشابه زیر را مشاهده کنید:

Hello from Flask app! Connected to DB at db_service:5432 with user myuser for database mydatabase.

بررسی وضعیت کانتینرها

برای مشاهده وضعیت کانتینرهای در حال اجرا، از دستور زیر استفاده کنید:

docker compose ps

خروجی باید چیزی شبیه به این باشد:

NAME                 COMMAND                  SERVICE             STATUS              PORTS
my_compose_app-db_service-1         "docker-entrypoint.sh…"   db_service          running             5432/tcp
my_compose_app-flask_app_service-1   "python app.py"          flask_app_service   running             5000/tcp
my_compose_app-nginx_service-1       "/docker-entrypoint.sh…"   nginx_service       running             0.0.0.0:80->80/tcp

مشاهده لاگ‌ها

برای مشاهده لاگ‌های تمام سرویس‌ها:

docker compose logs

برای مشاهده لاگ‌های یک سرویس خاص (مثلاً flask_app_service):

docker compose logs flask_app_service

توقف و حذف پروژه

برای توقف و حذف تمام کانتینرها، شبکه‌ها و حجم‌های پیش‌فرض ایجاد شده توسط Compose، دستور زیر را اجرا کنید:

docker compose down

اگر می‌خواهید حجم‌های داده‌ای (مانند db_data) نیز حذف شوند، از فلگ -v استفاده کنید:

docker compose down -v

این مثال ساده، قدرت و سادگی Docker Compose را در مدیریت یک برنامه چندکانتینری نشان می‌دهد. با این پایه، می‌توانید پروژه‌های پیچیده‌تری را تعریف و مدیریت کنید.

دستورات پرکاربرد Docker Compose: کنترل کامل بر برنامه‌هایتان

پس از آشنایی با ساختار فایل docker-compose.yml و یک مثال عملی، نوبت به تسلط بر دستورات خط فرمان Docker Compose می‌رسد. این دستورات به شما امکان می‌دهند تا چرخه حیات کامل برنامه‌های چندکانتینری خود را کنترل کنید.

قبل از اجرای هر دستور، مطمئن شوید که در دایرکتوری اصلی پروژه حاوی فایل docker-compose.yml قرار دارید. در ادامه، دستورات پرکاربرد را بررسی می‌کنیم.

docker compose up: راه‌اندازی و ساخت پروژه

این دستور اصلی‌ترین دستور Docker Compose است. مسئول ساخت (در صورت لزوم)، ایجاد، شروع و پیوند کانتینرهای سرویس‌های تعریف شده در فایل docker-compose.yml است.

  • docker compose up:

    پروژه را در حالت پیش‌زمینه (foreground) راه‌اندازی می‌کند. لاگ‌های تمام سرویس‌ها در ترمینال نمایش داده می‌شود. اگر از این حالت استفاده می‌کنید، می‌توانید با Ctrl+C کانتینرها را متوقف کنید (بدون حذف).

    docker compose up
    
  • docker compose up -d:

    پروژه را در حالت جدا شده (detached mode) یا پس‌زمینه راه‌اندازی می‌کند. کانتینرها شروع به کار می‌کنند و کنترل ترمینال به شما باز می‌گردد. این حالت برای محیط‌های تولید یا زمانی که نمی‌خواهید لاگ‌ها ترمینال را اشغال کنند، مفید است.

    docker compose up -d
    
  • docker compose up --build:

    قبل از راه‌اندازی کانتینرها، ایمیج‌های مرتبط با سرویس‌هایی که دارای بخش build هستند را دوباره می‌سازد. این مفید است زمانی که تغییراتی در Dockerfile یا کد برنامه خود ایجاد کرده‌اید.

    docker compose up -d --build
    
  • docker compose up --force-recreate:

    کانتینرها را حتی اگر تغییری در پیکربندی آن‌ها ایجاد نشده باشد، دوباره می‌سازد و جایگزین می‌کند. این می‌تواند برای رفع مشکلات غیرمنتظره مفید باشد.

    docker compose up -d --force-recreate
    
  • docker compose up --no-deps SERVICE_NAME:

    یک سرویس خاص را بدون راه‌اندازی وابستگی‌های آن (سرویس‌هایی که در depends_on ذکر شده‌اند) راه‌اندازی می‌کند. معمولاً توصیه نمی‌شود مگر اینکه دقیقاً بدانید چه کاری انجام می‌دهید.

    docker compose up --no-deps flask_app_service
    

docker compose down: توقف و حذف پروژه

این دستور برای متوقف کردن و حذف کانتینرها، شبکه‌ها و حجم‌های داده‌ای (در صورت درخواست) که توسط docker compose up ایجاد شده‌اند، استفاده می‌شود.

  • docker compose down:

    کانتینرها و شبکه‌های پیش‌فرض پروژه را متوقف کرده و حذف می‌کند.

    docker compose down
    
  • docker compose down -v:

    علاوه بر کانتینرها و شبکه‌ها، تمام حجم‌های داده‌ای تعریف شده و unnamed volumes (حجم‌های داده‌ای بی‌نام) را نیز حذف می‌کند. با احتیاط استفاده شود، زیرا داده‌های پایدار شما حذف خواهند شد.

    docker compose down -v
    
  • docker compose down --rmi all:

    علاوه بر حذف کانتینرها و شبکه‌ها، تمام ایمیج‌های استفاده شده توسط سرویس‌ها را نیز حذف می‌کند.

    docker compose down --rmi all
    
  • docker compose down --remove-orphans:

    کانتینرهایی که دیگر در فایل docker-compose.yml تعریف نشده‌اند، اما به عنوان بخشی از پروژه در حال اجرا هستند را حذف می‌کند.

    docker compose down --remove-orphans
    

docker compose ps: مشاهده وضعیت سرویس‌ها

لیست کانتینرهای در حال اجرا (و متوقف شده) برای پروژه جاری را نمایش می‌دهد.

docker compose ps

خروجی شامل نام، دستور، سرویس، وضعیت و پورت‌های نقشه‌برداری شده خواهد بود.

docker compose logs: مشاهده لاگ‌های سرویس‌ها

لاگ‌های خروجی تمام سرویس‌ها یا یک سرویس خاص را نمایش می‌دهد.

  • docker compose logs:

    نمایش لاگ‌های تمام سرویس‌ها.

    docker compose logs
    
  • docker compose logs SERVICE_NAME:

    نمایش لاگ‌های یک سرویس خاص.

    docker compose logs flask_app_service
    
  • docker compose logs -f SERVICE_NAME:

    مشاهده لاگ‌ها به صورت لحظه‌ای (follow mode).

    docker compose logs -f flask_app_service
    
  • docker compose logs --tail N SERVICE_NAME:

    نمایش N خط آخر لاگ‌ها.

    docker compose logs --tail 100 flask_app_service
    

docker compose exec: اجرای دستور در کانتینر در حال اجرا

این دستور به شما امکان می‌دهد تا یک دستور را در یک کانتینر در حال اجرا اجرا کنید.

docker compose exec SERVICE_NAME COMMAND

مثال: ورود به shell کانتینر Flask

docker compose exec flask_app_service sh

مثال: اجرای دستور در کانتینر PostgreSQL

docker compose exec db_service psql -U myuser mydatabase

docker compose start/stop/restart: کنترل سرویس‌ها

برای شروع، توقف یا راه‌اندازی مجدد سرویس‌های خاص یا تمام سرویس‌ها بدون نیاز به بازسازی.

  • docker compose start [SERVICE_NAME...]:

    شروع سرویس‌های متوقف شده.

    docker compose start flask_app_service
    
  • docker compose stop [SERVICE_NAME...]:

    توقف سرویس‌های در حال اجرا.

    docker compose stop nginx_service
    
  • docker compose restart [SERVICE_NAME...]:

    راه‌اندازی مجدد سرویس‌ها.

    docker compose restart flask_app_service db_service
    

docker compose build: ساخت ایمیج‌ها

این دستور ایمیج‌های مربوط به سرویس‌هایی که دارای بخش build در docker-compose.yml هستند را می‌سازد. مفید است اگر می‌خواهید ایمیج‌ها را قبل از up به صورت جداگانه بسازید.

docker compose build

برای ساخت مجدد (force rebuild) با حذف کش:

docker compose build --no-cache

docker compose config: اعتبارسنجی و نمایش پیکربندی

این دستور پیکربندی نهایی Compose را پس از اعمال تمام فایل‌های Compose و متغیرهای محیطی نمایش می‌دهد. برای اشکال‌زدایی و اعتبارسنجی فایل docker-compose.yml بسیار مفید است.

docker compose config

برای بررسی اعتبار پیکربندی بدون نمایش آن:

docker compose config --quiet

docker compose run: اجرای یک دستور یکبار مصرف در سرویس

این دستور یک کانتینر جدید بر اساس سرویس مشخص شده ایجاد می‌کند و یک دستور خاص را در آن اجرا می‌کند، سپس کانتینر را حذف می‌کند. بر خلاف exec که در یک کانتینر در حال اجرا دستور را اجرا می‌کند، run یک کانتینر جدید ایجاد می‌کند.

docker compose run SERVICE_NAME COMMAND

مثال: اجرای یک shell در یک کانتینر موقت Flask (بدون پورت‌های نقشه‌برداری شده)

docker compose run flask_app_service sh

مثال: اجرای migration‌های پایگاه داده:

docker compose run db_service python manage.py migrate

با تسلط بر این دستورات، شما می‌توانید کنترل کاملی بر روی برنامه‌های چندکانتینری خود داشته باشید، از توسعه و اشکال‌زدایی گرفته تا استقرار و نگهداری.

مدیریت شبکه‌ها و حجم‌ها (Volumes) در Docker Compose: ارتباط و پایداری داده‌ها

یکی از جنبه‌های کلیدی در طراحی و پیاده‌سازی برنامه‌های کانتینری، مدیریت ارتباطات بین کانتینرها و اطمینان از پایداری داده‌ها است. Docker Compose با فراهم آوردن ابزارهایی برای تعریف و پیکربندی شبکه‌ها و حجم‌های داده‌ای، این چالش‌ها را به سادگی حل می‌کند.

شبکه‌های سفارشی (Custom Networks)

به طور پیش‌فرض، زمانی که شما یک پروژه Docker Compose را راه‌اندازی می‌کنید، Compose یک شبکه bridge به نام projectname_default ایجاد می‌کند و تمام سرویس‌های تعریف شده در فایل docker-compose.yml را به آن متصل می‌کند. این باعث می‌شود که کانتینرها بتوانند با استفاده از نام سرویس (که به عنوان hostname عمل می‌کند) با یکدیگر ارتباط برقرار کنند. با این حال، در سناریوهای پیچیده‌تر، ممکن است بخواهید شبکه‌های سفارشی برای ایزوله‌سازی بهتر یا طراحی خاص شبکه ایجاد کنید.

چرا از شبکه‌های سفارشی استفاده کنیم؟

  • ایزوله‌سازی: می‌توانید سرویس‌های مختلف را در شبکه‌های جداگانه قرار دهید تا از ارتباط ناخواسته جلوگیری کنید. مثلاً، یک شبکه برای سرویس‌های بک‌اند و یک شبکه دیگر برای سرویس‌های فرانت‌اند که فقط با بک‌اند در ارتباط هستند.
  • کنترل بیشتر: می‌توانید پارامترهای شبکه مانند درایور (bridge، overlay، host) را سفارشی‌سازی کنید.
  • نام‌گذاری معنی‌دار: به جای نام پیش‌فرض، می‌توانید نام‌های معنی‌دار برای شبکه‌های خود انتخاب کنید.

تعریف شبکه‌های سفارشی در docker-compose.yml

برای تعریف یک شبکه سفارشی، از کلید سطح بالای networks در فایل docker-compose.yml استفاده می‌کنید:

version: "3.8"

services:
  web_frontend:
    image: nginx
    ports:
      - "80:80"
    networks:
      - frontend_network
      - backend_network # اگر نیاز به دسترسی به بک‌اند هم دارد

  api_backend:
    build: ./api
    expose:
      - "8000"
    networks:
      - backend_network

  database:
    image: postgres
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - backend_network

networks:
  frontend_network:
    driver: bridge # پیش‌فرض است، می‌توانید حذف کنید
  backend_network:
    driver: bridge # پیش‌فرض است، می‌توانید حذف کنید

در این مثال:

  • ما دو شبکه سفارشی به نام‌های frontend_network و backend_network تعریف کرده‌ایم.
  • سرویس web_frontend به frontend_network و backend_network متصل است (فرانت‌اند به دنیای بیرون و بک‌اند متصل است).
  • سرویس‌های api_backend و database فقط به backend_network متصل هستند، به این معنی که فقط می‌توانند با یکدیگر و با سرویس‌های دیگری که به این شبکه متصل هستند (مانند web_frontend) ارتباط برقرار کنند.

با این پیکربندی، web_frontend می‌تواند با api_backend ارتباط برقرار کند (با نام api_backend در پورت 8000)، اما سرویس api_backend مستقیماً از طریق پورت 80 به دنیای بیرون متصل نیست و فقط Nginx می‌تواند به آن دسترسی داشته باشد.

حجم‌های داده (Volumes)

یکی از چالش‌های اصلی در کانتینرسازی، پایداری داده‌ها است. کانتینرها به طور پیش‌فرض بی‌حالت (stateless) هستند و هر داده‌ای که درون کانتینر ذخیره شود، با حذف کانتینر از بین می‌رود. برای اطمینان از پایداری داده‌ها، Docker مفهوم Volumes را معرفی کرده است.

انواع Volumes در Docker Compose

Compose از دو نوع اصلی Volume پشتیبانی می‌کند:

  1. Bind Mounts:

    یک فایل یا دایرکتوری از سیستم فایل هاست را مستقیماً به یک مسیر در کانتینر mount می‌کند. تغییرات در هر دو طرف (هاست و کانتینر) بلافاصله منعکس می‌شود. این روش برای توسعه محلی و mount کردن کد منبع یا فایل‌های پیکربندی بسیار مفید است.

    نحوه تعریف در سرویس:

    services:
      app:
        image: myapp
        volumes:
          - ./src:/app/src # mount کردن کد منبع از هاست به کانتینر
          - ./config/nginx.conf:/etc/nginx/nginx.conf:ro # mount کردن فایل پیکربندی فقط خواندنی
    
  2. Named Volumes:

    این نوع Volume توسط Docker مدیریت می‌شود و یک بخش جداگانه از سیستم فایل هاست (معمولاً در /var/lib/docker/volumes/ در Linux) را به کانتینر mount می‌کند. Named Volumes بهترین راه برای پایداری داده‌ها در محیط‌های تولید هستند، زیرا Docker آن‌ها را مدیریت می‌کند و مستقل از چرخه حیات کانتینرها هستند.

    نحوه تعریف در docker-compose.yml:

    ابتدا، Named Volume را در کلید سطح بالای volumes تعریف می‌کنید:

    version: "3.8"
    
    services:
      db:
        image: postgres:16
        environment:
          POSTGRES_DB: mydatabase
          POSTGRES_USER: myuser
          POSTGRES_PASSWORD: mysecretpassword
        volumes:
          - db_data:/var/lib/postgresql/data # mount کردن named volume به مسیر داده‌های PostgreSQL
    
    volumes:
      db_data: # تعریف named volume
    

    در این مثال، db_data یک Named Volume است که توسط Docker مدیریت می‌شود. حتی اگر کانتینر db حذف شود، داده‌های ذخیره شده در db_data باقی می‌مانند و می‌توانند توسط یک کانتینر جدید دوباره mount شوند.

مزایای استفاده از Named Volumes:

  • مدیریت آسان: Docker حجم‌ها را مدیریت می‌کند، شما نگران مکان ذخیره‌سازی دقیق نیستید.
  • پایداری داده‌ها: داده‌ها حتی پس از حذف کانتینرها باقی می‌مانند.
  • بهره‌وری بالا: Named Volumes معمولاً عملکرد I/O بهتری نسبت به Bind Mounts دارند، به خصوص در Linux.
  • امنیت: Named Volumes محدودیت‌های دسترسی کمتری نسبت به Bind Mounts دارند، که می‌تواند در برخی موارد امنیتی مزیت باشد.

با ترکیب قدرت شبکه‌های سفارشی برای کنترل ارتباطات و حجم‌های داده‌ای برای پایداری داده‌ها، Docker Compose به شما امکان می‌دهد تا برنامه‌های کانتینری قدرتمند، انعطاف‌پذیر و قابل اعتماد را طراحی و پیاده‌سازی کنید.

بهترین شیوه‌ها (Best Practices) و نکات پیشرفته در استفاده از Docker Compose

برای بهره‌وری حداکثری از Docker Compose و ساخت محیط‌های توسعه و استقرار قوی‌تر و پایدارتر، رعایت بهترین شیوه‌ها و آشنایی با نکات پیشرفته ضروری است. این بخش به شما کمک می‌کند تا از اشتباهات رایج جلوگیری کرده و پروژه‌های Compose خود را بهینه‌سازی کنید.

۱. فایل‌های .env و متغیرهای محیطی: مدیریت پیکربندی‌ها

سرویس‌های شما اغلب به متغیرهای محیطی برای پیکربندی نیاز دارند، مانند رمز عبور پایگاه داده، کلیدهای API، یا نام میزبان‌ها. ذخیره این اطلاعات به صورت مستقیم در docker-compose.yml توصیه نمی‌شود، به خصوص اگر فایل در کنترل نسخه عمومی باشد. بهترین راه استفاده از فایل .env است.

استفاده از فایل .env

شما می‌توانید یک فایل به نام .env در کنار فایل docker-compose.yml خود ایجاد کنید. متغیرهای تعریف شده در این فایل به صورت خودکار توسط Compose بارگذاری شده و می‌توانند در docker-compose.yml استفاده شوند.

مثال .env:

# .env
POSTGRES_PASSWORD=my_secure_db_password
APP_PORT=8080

مثال docker-compose.yml با استفاده از متغیرها:

version: "3.8"

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # استفاده از متغیر از .env
    ports:
      - "${APP_PORT}:5432" # استفاده از متغیر از .env

  web:
    image: myapp
    ports:
      - "${APP_PORT}:80"

نکته مهم: فایل .env را هرگز در سیستم کنترل نسخه (مانند Git) قرار ندهید. آن را به .gitignore اضافه کنید.

env_file در پیکربندی سرویس

همچنین می‌توانید از env_file در تعریف سرویس استفاده کنید تا متغیرهای محیطی را از یک فایل مشخص بارگذاری کنید. این روش زمانی مفید است که می‌خواهید برای هر سرویس یک فایل متغیر محیطی جداگانه داشته باشید.

services:
  app:
    image: myapp
    env_file:
      - ./config/app.env # بارگذاری متغیرها از app.env

۲. فایل‌های Docker Compose چندگانه (Multiple Compose Files)

در پروژه‌های بزرگ‌تر، ممکن است بخواهید پیکربندی‌های مختلفی برای محیط‌های مختلف (توسعه، تست، تولید) داشته باشید. Docker Compose به شما امکان می‌دهد چندین فایل Compose را با هم ترکیب کنید. این کار با استفاده از فلگ -f (یا --file) انجام می‌شود.

سناریو: یک فایل پایه docker-compose.yml برای پیکربندی مشترک، و یک فایل docker-compose.dev.yml برای تنظیمات توسعه.

docker-compose.yml (پیکربندی پایه):

version: "3.8"
services:
  web:
    image: myapp
    build: .
    volumes:
      - .:/app # mount کردن کد برای توسعه
    ports:
      - "80:80"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: password

docker-compose.dev.yml (تنظیمات توسعه، برای گسترش یا جایگزینی):

version: "3.8"
services:
  web:
    command: ["python", "manage.py", "runserver", "0.0.0.0:80"] # اجرای سرور توسعه
    ports:
      - "8000:80" # تغییر پورت برای توسعه
  db:
    ports:
      - "5432:5432" # اکسپوز کردن پورت دیتابیس برای دسترسی مستقیم

برای راه‌اندازی پروژه با هر دو فایل:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

Compose فایل‌ها را به ترتیب ادغام می‌کند. تنظیمات در فایل‌های بعدی، تنظیمات قبلی را بازنویسی می‌کنند.

۳. استفاده از Health Checks

depends_on فقط تضمین می‌کند که یک سرویس قبل از دیگری راه‌اندازی شود، نه اینکه آن سرویس کاملاً “آماده” (healthy) و قابل استفاده باشد. برای مثال، پایگاه داده ممکن است راه‌اندازی شده باشد، اما هنوز آماده پذیرش اتصالات نباشد. Health Checks به شما امکان می‌دهند تا وضعیت سلامت یک کانتینر را بررسی کنید.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: mysecretpassword
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s # هر 5 ثانیه چک شود
      timeout: 5s # در صورت عدم پاسخ در 5 ثانیه، ناموفق
      retries: 5 # 5 بار امتحان شود قبل از اعلام ناسالم بودن
      start_period: 10s # 10 ثانیه به کانتینر فرصت داده شود تا شروع به کار کند
  
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy # وب فقط زمانی شروع به کار کند که db سالم باشد

با condition: service_healthy در depends_on، سرویس web تنها زمانی شروع به کار می‌کند که Docker Health Check سرویس db را “سالم” اعلام کند. این رویکرد به جلوگیری از خطاهای “عدم اتصال به پایگاه داده” در هنگام راه‌اندازی کمک می‌کند.

۴. بهینه‌سازی برای محیط پروداکشن (Production Considerations)

Docker Compose در درجه اول برای محیط‌های توسعه طراحی شده است، اما با چند تنظیم می‌توان آن را برای استقرارهای کوچک و متوسط در تولید نیز به کار برد.

  • منابع:

    محدود کردن منابع CPU و RAM برای سرویس‌ها برای جلوگیری از مصرف بیش از حد منابع و پایداری بیشتر.

    services:
      web:
        image: myapp:latest
        deploy: # برای Docker Swarm و در برخی موارد Docker Compose
          resources:
            limits:
              cpus: '0.5' # 0.5 هسته CPU
              memory: 512M # 512 مگابایت رم
            reservations:
              cpus: '0.25'
              memory: 256M
    
  • سیاست بازراه‌اندازی (Restart Policy):

    استفاده از restart: always یا restart: on-failure برای اطمینان از این که سرویس‌ها پس از خرابی یا بازراه‌اندازی سیستم، به صورت خودکار دوباره شروع به کار می‌کنند.

    services:
      web:
        image: myapp:latest
        restart: always
    
  • فایل‌های پیکربندی تولید:

    استفاده از فایل‌های Compose چندگانه برای جدا کردن پیکربندی‌های توسعه و تولید. مثلاً docker-compose.yml برای پایه، docker-compose.dev.yml برای توسعه و docker-compose.prod.yml برای تولید.

    # docker-compose.prod.yml
    services:
      web:
        build:
          context: .
          dockerfile: Dockerfile.prod
        environment:
          DEBUG: "False"
          # ... سایر متغیرهای محیطی تولید
    
  • لاگ‌برداری:

    پیکربندی درایورهای لاگ‌برداری (مانند json-file, syslog, fluentd) برای مدیریت بهتر لاگ‌ها در محیط تولید.

    services:
      web:
        image: myapp:latest
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "3"
    
  • پایش (Monitoring):

    ادغام با ابزارهای پایش خارجی. Docker Compose به تنهایی ابزارهای پایش گسترده‌ای ندارد.

۵. زمان ارتقاء به ابزارهای اورکستراسیون (Swarm/Kubernetes)

در حالی که Docker Compose برای استقرارهای کوچک تا متوسط و محیط‌های توسعه بسیار عالی است، برای برنامه‌های بسیار بزرگ، پیچیده و با نیاز به مقیاس‌پذیری و پایداری بالا، ابزارهای اورکستراسیون مانند Docker Swarm یا Kubernetes گزینه‌های بهتری هستند. Docker Compose می‌تواند به عنوان یک پله برای یادگیری مفاهیم اورکستراسیون عمل کند، زیرا فایل‌های docker-compose.yml (نسخه 3) می‌توانند به عنوان docker stack deploy در Docker Swarm نیز استفاده شوند.

با پیروی از این بهترین شیوه‌ها و استفاده از نکات پیشرفته، می‌توانید از Docker Compose به طور موثرتری استفاده کنید، پیچیدگی‌های مدیریت کانتینرها را کاهش دهید و محیط‌های توسعه و استقرار قوی‌تری بسازید.

نتیجه‌گیری: قدرت Docker Compose در دستان شما

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

شما آموختید که Docker Compose چگونه با استفاده از یک فایل پیکربندی YAML، فرآیند تعریف، راه‌اندازی و مدیریت مجموعه‌ای از سرویس‌های کانتینری را ساده‌سازی می‌کند. این ابزار نه تنها پیچیدگی‌های مدیریت دستی کانتینرها را کاهش می‌دهد، بلکه با افزایش تکرارپذیری، همکاری تیمی را تسهیل کرده و یکپارچگی محیط‌های توسعه و تولید را تضمین می‌کند. توانایی تعریف شبکه‌های سفارشی برای ایزوله‌سازی ارتباطات و استفاده از حجم‌های داده‌ای برای پایداری اطلاعات، از ویژگی‌های کلیدی است که به شما امکان ساخت برنامه‌های قدرتمندتر و مقاوم‌تر را می‌دهد.

ما همچنین بر اهمیت بهترین شیوه‌ها، مانند مدیریت متغیرهای محیطی با استفاده از فایل‌های .env، استفاده استراتژیک از فایل‌های Compose چندگانه برای محیط‌های مختلف، و پیاده‌سازی Health Checks برای اطمینان از آمادگی سرویس‌ها تأکید کردیم. این نکات و ترفندهای پیشرفته به شما کمک می‌کنند تا از مشکلات رایج جلوگیری کرده و محیط‌های کانتینری خود را به بهترین شکل ممکن بهینه‌سازی کنید.

Docker Compose در قلب بسیاری از جریان‌های کاری توسعه مدرن قرار دارد و یک ابزار ضروری برای هر توسعه‌دهنده، مهندس DevOps یا مدیر سیستمی است که با کانتینرها کار می‌کند. با این حال، به یاد داشته باشید که این ابزار تنها یک گام در مسیر بزرگ‌تر اورکستراسیون کانتینرها است. برای مقیاس‌های بزرگ‌تر و سناریوهای پیچیده‌تر تولید، یادگیری و استفاده از ابزارهایی مانند Docker Swarm یا Kubernetes گام منطقی بعدی خواهد بود.

امیدواریم این آموزش به شما بینش و مهارت‌های لازم برای شروع قدرتمند با Docker Compose را ارائه داده باشد. حالا نوبت شماست که این دانش را به کار بگیرید، پروژه‌های خود را با Docker Compose تعریف و مدیریت کنید، و از مزایای بی‌شمار کانتینرسازی بهره‌مند شوید. دنیای کانتینرها با Docker Compose در دستان شماست. به کاوش ادامه دهید و نوآوری کنید!

“تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”

قیمت اصلی 2.290.000 ریال بود.قیمت فعلی 1.590.000 ریال است.

"تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"

"با شرکت در این دوره جامع و کاربردی، به راحتی مهارت‌های برنامه‌نویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر می‌سازد تا به سرعت الگوریتم‌های پیچیده را درک کرده و اپلیکیشن‌های هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفه‌ای و امکان دانلود و تماشای آنلاین."

ویژگی‌های کلیدی:

بدون نیاز به تجربه قبلی برنامه‌نویسی

زیرنویس فارسی با ترجمه حرفه‌ای

۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان