پیکوسیستم خدمات فنی IT

docker compose چیست؟ آموزش فایل compose، دستورها و اشتباه های رایج

Docker Compose چند کانتینر یک برنامه را در یک فایل YAML تعریف می کند و با یک دستور بالا می آورد. نمونه فایل واقعی با دیتابیس، volume و healthcheck، دستورهای روزمره، مدیریت رمزها و حد استفاده از Compose را مرور می کنیم.

docker compose چیست؟ آموزش فایل compose، دستورها و اشتباه های رایج

docker compose چیست؟ ابزاری است که یک برنامه چندکانتینری را در یک فایل YAML توصیف می کند: وب اپ، دیتابیس، شبکه و volume همه در همان فایل می آیند و با یک دستور روی یک سرور بالا می روند. به جای چند دستور طولانی docker run که هر کدام را باید از حفظ بدانید، یک فایل دارید که در گیت نگه می شود، بازبینی می شود و روی هر سرور همان نتیجه را می دهد.

مشکلی که Compose حل می کند

برنامه واقعی تقریبا هیچ وقت یک کانتینر نیست. یک وب اپ به دیتابیس نیاز دارد، دیتابیس به دیسک ماندگار، و گاهی یک کش یا صف هم کنارشان هست. اگر این ها را با دستور دستی بسازید، ترتیب راه اندازی، نام شبکه، مقدار متغیرها و پورت ها فقط در حافظه یک نفر یا در یک فایل متنی گم شده می ماند. Compose این اطلاعات را به یک فایل compose.yaml منتقل می کند. سرویس ها داخل یک شبکه خصوصی مشترک قرار می گیرند و می توانند با نام سرویس همدیگر را پیدا کنند، یعنی برنامه به جای IP به db:3306 وصل می شود.

پیش نیاز، نصب خود داکر است. اگر هنوز نصب نکرده اید، اول نصب Docker روی Ubuntu و AlmaLinux را انجام دهید؛ Compose در آن نصب به صورت افزونه همراه است و با docker compose (با فاصله) اجرا می شود.

یک فایل docker-compose.yml واقعی

نمونه زیر یک وب اپ، یک دیتابیس MySQL، یک volume برای داده و سیاست ری استارت و healthcheck را کنار هم می گذارد. وب اپ از پوشه ./app ساخته می شود:

services:
  web:
    build: ./app
    image: registry.example.local/shop-web:1.4.2
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:3000"
    env_file:
      - ./app.env
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  db:
    image: mysql:8.4
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: shop
      MYSQL_USER: shop
      MYSQL_PASSWORD_FILE: /run/secrets/db_pass
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root
    volumes:
      - db_data:/var/lib/mysql
    secrets:
      - db_pass
      - db_root
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  db_data:

secrets:
  db_pass:
    file: ./secrets/db_pass.txt
  db_root:
    file: ./secrets/db_root.txt

چند نکته در این فایل عمدی است. پورت وب اپ به آدرس loopback یعنی 127.0.0.1 بسته شده و کاربران از طریق یک reverse proxy می آیند (پیکربندی Nginx reverse proxy). برای دیتابیس هیچ پورتی منتشر نشده، چون وب اپ از داخل شبکه Compose به آن می رسد. تگ ایمیج ها نسخه مشخص دارند. بخش depends_on با شرط service_healthy صبر می کند تا MySQL واقعا آماده پذیرش اتصال باشد و فقط به شروع شدن پروسه اکتفا نمی کند. اگر می خواهید دیتابیس را دقیق تر راه بیندازید، نصب و تنظیم MySQL جزئیات بیشتری دارد.

دستورهای اصلی Compose

دستور کار
docker compose up -d سرویس ها را می سازد و در پس زمینه اجرا می کند؛ فقط چیزهای تغییرکرده دوباره ساخته می شوند
docker compose ps وضعیت سرویس ها و نتیجه healthcheck را نشان می دهد
docker compose logs -f web لاگ زنده یک سرویس را نمایش می دهد
docker compose exec db mysql -u shop -p داخل کانتینر در حال اجرا دستور اجرا می کند
docker compose pull ایمیج های جدید همان تگ را می گیرد
docker compose down کانتینرها و شبکه را حذف می کند، volumeها را نگه می دارد

تفاوت down و down -v را جدی بگیرید. گزینه -v volumeها را هم پاک می کند و با آن دیتابیس هم می رود. روی سرور تولید این گزینه را فقط وقتی بزنید که مطمئنید داده بکاپ دارد. برای به روزرسانی معمولا همین دو دستور کافی است: اول pull، بعد up -d. خود Compose فقط سرویس هایی را دوباره می سازد که ایمیج یا تنظیمشان عوض شده است.

فایل env و secret؛ رمزها کجا بروند

سه جا برای تنظیمات وجود دارد و هرکدام کاربرد خودش را دارد. مقدارهای غیرحساس مثل آدرس سرویس ها یا سطح لاگ در environment یا env_file می نشینند. مقدارهای حساس مثل رمز دیتابیس بهتر است از فایل خوانده شوند؛ بخش secrets فایل را داخل کانتینر زیر /run/secrets/ می گذارد و ایمیج های رسمی مثل MySQL و PostgreSQL متغیرهایی با پسوند _FILE برای خواندنش دارند. فایل env هم چیزی است که باید از گیت بیرون بماند:

printf '.env\napp.env\nsecrets/\n' >> .gitignore
chmod 600 app.env secrets/*.txt
docker compose config

دستور docker compose config فایل نهایی را بعد از جایگزینی متغیرها چاپ می کند و خطای YAML را هم قبل از اجرا نشان می دهد. دقت کنید که خروجی آن رمزهای env را هم نمایش می دهد، پس آن را در لاگ CI یا چت نچسبانید. فایل .env کنار compose.yaml برای جایگزینی متغیرهای داخل خود فایل (${TAG}) خوانده می شود و با env_file که متغیر را به کانتینر می دهد فرق دارد؛ این دو را با هم قاطی نکنید.

Compose کی کافی است و کی باید سراغ Kubernetes رفت

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

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

دسته بندی سرویس ها، شبکه و ساخت خودکار

وقتی فایل بزرگ تر می شود، چند کار کمک می کند. شبکه ها را صریح تعریف کنید و دیتابیس را در شبکه ای قرار دهید که سرویس بیرونی به آن وصل نیست. برای کش مثل Redis سرویس جدا اضافه کنید (Redis چیست) و برای هر سرویس سقف حافظه تعیین کنید تا یک نشت حافظه کل سرور را نخواباند. فایل را در گیت نگه دارید و استقرار را به pipeline بسپارید، تا pull و up -d بدون دست زدن دستی اجرا شوند (CI/CD چیست). برای تفکیک محیط ها از چند فایل override یا از profiles استفاده می شود، ولی یک فایل پایه مشترک برای همه محیط ها داشته باشید تا staging و production از هم دور نشوند.

اشتباه های رایج

  • منتشر کردن پورت دیتابیس. خط "3306:3306" یعنی روی همه اینترفیس ها باز است و داکر قوانین فایروال را جداگانه اضافه می کند، پس UFW ممکن است جلویش را نگیرد. اگر دسترسی بیرونی لازم است، آن را به loopback (127.0.0.1:3306:3306) محدود کنید.
  • تگ latest. با هر pull ممکن است نسخه عوض شود و برنامه بعد از ری استارت ساده ای خراب شود. نسخه را بنویسید و عمدی ارتقا دهید.
  • نداشتن volume. داده ای که داخل کانتینر نوشته شود با حذف کانتینر از بین می رود. دیتابیس بدون volume را فقط برای تست بسازید.
  • نداشتن بکاپ از volume. برای دیتابیس از dump خود دیتابیس استفاده کنید و پوشه داده در حال اجرا را کپی نکنید.
  • رمز داخل فایل compose یا داخل ایمیج، یا ثبت فایل env در گیت.
  • اتکا به restart: always بدون healthcheck. کانتینر بالا اما بی جواب، سالم حساب می شود.
  • mount کردن /var/run/docker.sock داخل کانتینر بی دلیل؛ این کار دسترسی root به میزبان می دهد.

منابع و مستندات رسمی

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

نحوه تهیه مقاله ها

مقاله های مرتبط

استعلام

کارتان را بگویید، مسیر و هزینه را می گوییم

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

  1. 01درخواست را می خوانیم و اگر ابهامی بود تماس می گیریم.
  2. 02در صورت نیاز، بررسی اولیه ریموت یا بازدید انجام می شود.
  3. 03پیشنهاد مکتوب با دامنه کار، زمان بندی و هزینه می فرستیم.

اطلاعات شما فقط برای پاسخ به همین درخواست استفاده می شود. حریم خصوصی