راهنمای دستورات Docker Compose برای سرور واقعی
دستورات روزمره Docker Compose V2 را بر اساس کار دستهبندی کنید: اجرای سرویس، اعمال تغییر، لاگ، shell، شبکه، volume و پاکسازی ایمن، با نکته خطای compose.yaml.
فرمانهای Compose که واقعاً استفاده میکنید
Docker Compose بیش از 40 زیرفرمان دارد. کار روزانه روی یک سرور معمولاً به حدود 12 مورد نیاز دارد. این صفحه آنها را بر اساس کاری که انجام میدهید دستهبندی میکند، برای هرکدام یک دلیل ساده ارائه میدهد و در مواردی که فرمانی نکتهای مهم را پنهان میکند، به راهنمای جامع مربوطه ارجاع میدهد.
تمام مطالب اینجا از Compose V2 استفاده میکنند: docker compose با یک فاصله، نه اسکریپت قدیمی docker-compose. V2 یک افزونه Go است که همراه با Docker Engine نصب میشود. V1 از بستههای فعلی حذف شده است؛ بنابراین مشاهده docker-compose: command not found در یک سیستم Ubuntu تازه، در ژوئیه 2026، رفتاری مورد انتظار است و نشاندهنده خرابی نیست. با docker compose version بررسی کنید. اگر این فرمان چیزی چاپ نکرد، بسته docker-compose-plugin را نصب کنید.
هر فرمان زیر باید از پوشهای اجرا شود که compose.yaml شما را در خود دارد؛ زیرا Compose نام پروژه را از همان پوشه میگیرد و فایل را نسبت به آن پیدا میکند. اگر همان فرمان را یک سطح بالاتر اجرا کنید، Compose با no configuration file provided: not found متوقف میشود. اگر قالب فایل برایتان جدید است، با اولین فایل Compose روی یک VPS شروع کنید و سپس برای فرمانها به این صفحه برگردید.
چرخه عمر: چهار دستور که وارد میکنید و یک دستور که کانتینرها را حذف میکند
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d شبکه را ایجاد میکند، کانتینرها را میسازد، آنها را اجرا میکند و بازمیگردد. این دستور بهمحض ایجاد کانتینرها بازمیگردد. به همین دلیل، اسکریپت استقرار که بلافاصله پس از آن یک بررسی curl اجرا میکند، اغلب در نخستین تلاش شکست میخورد. up -d --wait تا زمانی مسدود میماند که هر سرویسی که healthcheck تعریف کرده است، وضعیت سالم گزارش دهد. اگر یکی از سرویسها هرگز به این وضعیت نرسد، این دستور با کد خروجی غیرصفر خاتمه مییابد. این پرچم فقط به اندازه بررسیای قابل اعتماد است که پشت آن قرار دارد؛ بنابراین، پیش از اتکا به آن در خودکارسازی، یک healthcheck بنویسید که Compose بتواند به آن اعتماد کند.
stop کانتینرها را متوقف میکند و آنها را نگه میدارد؛ بنابراین، start همان کانتینرها را با همان لایه قابلنوشتن دوباره اجرا میکند. down کانتینرها را متوقف میکند و سپس کانتینرها و شبکه پروژه را حذف میکند. هر چیزی که داخل کانتینر و خارج از یک volume نوشته شده باشد، همراه آنها حذف میشود. این پرهزینهترین برداشت نادرست درباره Compose است و تفاوت کامل بین down و stop توضیح میدهد که این تفاوت در کجا مشکل ایجاد میکند.
restart یک reload نیست. این دستور همان کانتینر را با پیکربندی موجود در آن متوقف و دوباره اجرا میکند؛ بنابراین، تغییر متغیر محیطی، tag جدید image یا ویرایش نگاشت port هیچ اثری ندارد. برای اعمال تغییر فایل، دوباره up -d را اجرا کنید. Compose هر سرویس را با کانتینر در حال اجرای آن مقایسه میکند و فقط سرویسهایی را که پیکربندیشان تغییر کرده است، دوباره ایجاد میکند.
اعمال تغییر: ایجاد مجدد، دریافت، یا بازسازی
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d بهتنهایی، وقتی تغییری ایجاد نشده باشد، کاری انجام نمیدهد؛ همین ویژگی اجرای مکرر آن را ایمن میکند. --force-recreate این مقایسه را نادیده میگیرد و همه کانتینرها را حتی زمانی که پیکربندی یکسان است جایگزین میکند؛ بنابراین سریعترین روش برای پاککردن وضعیت غیرعادی داخل کانتینر است.
بهروزرسانی یک image به 2 دستور نیاز دارد، زیرا این 2 دستور کارهای متفاوتی انجام میدهند. pull، image فعلی را برای هر tag نامبردهشده در فایل دریافت میکند. سپس up -d متوجه میشود که ID مربوط به image سرویس دیگر با کانتینر در حال اجرای آن مطابقت ندارد و کانتینر را دوباره ایجاد میکند. اگر pull را انجام ندهید، up -d همان latest ماه گذشته را بدون خطا در حال اجرا نگه میدارد.
build برای سرویسهایی کاربرد دارد که بهجای بخش image:، بخش build: را تعریف میکنند. up -d --build در یک مرحله build و start را انجام میدهد و در زمان تغییر کد، روند معمول همین است. فقط زمانی از --no-cache استفاده کنید که یک لایهٔ cacheشده بهوضوح قدیمی باشد، زیرا این دستور همه لایهها را از ابتدا بازسازی میکند.
مشاهده آنچه در حال اجرا است
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps فقط کانتینرهای در حال اجرا را فهرست میکند. سرویسی که هنگام راهاندازی از کار افتاده باشد، تا زمانی که -a را اضافه نکنید در آن دیده نمیشود؛ بنابراین کانتینری که در ps وجود ندارد، در حالی که ps -a آن را بهصورت Exited (1) نشان میدهد، الگوی معمول شکست در راهاندازی است. کد خروج را بخوانید، سپس لاگها را بررسی کنید.
logs -f همه سرویسها را همزمان دنبال میکند و ابتدای هر خط نام سرویس را میآورد. این همان نمایی است که هنگام ارتباط سرویسها با یکدیگر و اهمیت ترتیب رویدادها به آن نیاز دارید. برای محدود کردن خروجی، نام یک سرویس را مشخص کنید. --tail=100 برای کانتینری که یک ماه است فعال بوده اهمیت دارد، زیرا حالت پیشفرض کل تاریخچه را چاپ میکند و ترمینال را پر میکند. --since 15m به پرسشی پاسخ میدهد که معمولاً دارید: هنگام راهاندازی مجددی که بهتازگی انجام دادهاید چه اتفاقی افتاد.
top پردازههای داخل هر کانتینر را فهرست میکند. این کار تفاوت میان «کانتینر در حال اجرا است» و «پردازه داخل آن در حال اجرا است» را مشخص میکند. ls از پوشه فعلی خارج میشود و همه پروژههای Compose موجود روی میزبان را همراه با وضعیتشان فهرست میکند؛ بنابراین میتوانید پشتهای را که سه ماه پیش راهاندازی کردهاید پیدا کنید.
ورود به یک shell درون سرویس
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec یک فرمان را درون containerای اجرا میکند که از قبل در حال اجراست. run یک container جدید را بر اساس همان service definition راهاندازی میکند؛ این روش زمانی لازم است که سرویس بهاندازه کافی پایدار نمیماند تا بتوان با exec وارد آن شد. همیشه run را همراه با --rm بهکار ببرید، زیرا در غیر این صورت هر بار اجرا یک container متوقفشده بر جای میگذارد و این containerها بهتدریج انباشته میشوند تا زمانی که docker compose ps -a دیگر قابل خواندن نباشد.
پیش از bash، sh را امتحان کنید. imageهای مبتنی بر Alpine فاقد bash هستند و خطا بهصورت exec: "bash": executable file not found in $PATH نمایش داده میشود. افزودن --no-deps به run وابستگیهای سرویس را نادیده میگیرد و از راهاندازی کل database برای یک بررسی سریع پیکربندی جلوگیری میکند.
run --rm web env سریعترین روش برای مشاهده محیطی است که سرویس واقعاً دریافت کرده است؛ پس از آنکه همه فایلهای .env، بلوکهای environment: و متغیرهای shell با یکدیگر ادغام شدهاند. وقتی یک مقدار نادرست است، معمولاً ترتیب ادغام علت آن است و نحوه حل env fileها و secretها در Compose مشخص میکند کدام منبع اولویت دارد.
شبکهها، پورتها و تفکیک نام
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksCompose همه سرویسها را در یک شبکه پروژه قرار میدهد و نام هر سرویس، یک نام DNS در آن شبکه است. اجرای getent hosts db داخل web، در صورت موفق بودن تفکیک نام، IP کانتینر را چاپ میکند و در غیر این صورت چیزی چاپ نمیکند؛ بنابراین در 2 ثانیه مشخص میکند که «آیا این کانتینرها میتوانند یکدیگر را ببینند؟». اگر نام تفکیک شود اما اتصال رد شود، فرایند داخل db به 127.0.0.1 متصل شده است، نه 0.0.0.0؛ بنابراین هرگز بستهای را از کانتینر دیگر نمیپذیرد. توضیح کامل این مدل در نحوه کار شبکههای Compose و DNS سرویسها آمده است.
port web 80 نشانی میزبان و پورتی را چاپ میکند که یک پورت کانتینر روی آن منتشر شده است. این کار زمانی که نگاشت از یک متغیر آمده باشد، از حدسزدن جلوگیری میکند. انتشار یک پورت همچنین یک قانون فایروال ایجاد میکند که Docker آن را مدیریت میکند. این قانون پیش از قوانین شما اعمال میشود؛ بنابراین سرویسی که تصور میکردید خصوصی است، ممکن است در اینترنت در دسترس باشد. این وضعیت در دلیل عبور پورتهای منتشرشده Docker از ufw توضیح داده شده است.
Volumeها و دادهها
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes، Volumeهای نامگذاریشدهای را که پروژه تعریف کرده است، هرکدام در یک خط چاپ میکند. از همین فهرست باید نسخه پشتیبان تهیه کنید. cp، فایل را بدون باز کردن shell، به داخل container یا از آن خارج میکند؛ در این دستور، قالب service:path در سمتی قرار میگیرد که container است.
down -v، این Volumeهای نامگذاریشده را همراه با containerها حذف میکند. این دستور برای برچیدن یک stack آزمایشی مناسب است، اما برای هر چیزی که دادههای مهم شما را نگهداری میکند نامناسب است؛ زیرا هیچ تأییدی درخواست نمیکند و امکان بازگردانی ندارد. Bind mountها از این عملیات جان سالم بهدر میبرند، زیرا روی filesystem میزبان قرار دارند. همین تفاوت در دامنه خسارت یکی از دلایلی است که باید بین Bind mountها و Volumeهای نامگذاریشده آگاهانه انتخاب کنید.
پاکسازی که بدون از دست دادن داده، فضای دیسک آزاد میکند
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans کانتینرهایی را حذف میکند که به پروژه تعلق دارند، اما دیگر در فایل ظاهر نمیشوند؛ این دقیقاً پس از تغییر نام یک سرویس رخ میدهد. بدون این گزینه، آن کانتینرها همچنان اجرا میشوند و برای docker compose ps قابل مشاهده نیستند.
docker system df پیش از حذف هر چیزی نشان میدهد فضای دیسک در کجا مصرف شده است و imageها، کانتینرها، volumeهای محلی و build cache را همراه با مقدار قابلبازیابی هرکدام جداگانه نمایش میدهد. image prune -a تمام imageهایی را حذف میکند که هیچ tagی به آنها اشاره نمیکند. در سیستمی که چند نسخه از یک image بزرگ را دریافت کرده است، این کار معمولاً بیشترین فضا را آزاد میکند. builder prune build cache را پاک میکند؛ این cache در هر سروری که imageهای خود را میسازد، بهتدریج رشد میکند.
هیچیک از این گزینهها به volumeهای نامگذاریشده دست نمیزنند. فقط docker volume prune و docker compose down -v این کار را انجام میدهند.
بررسی فایل پیش از ایجاد مشکل
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet در صورت موفقیت هیچ خروجیای چاپ نمیکند؛ بنابراین باید آن را در مرحله پیش از استقرار یا یک hook در git قرار دهید. دستور ساده config فایل کاملاً ادغامشده و درونیابیشده را چاپ میکند. با این روش میتوانید تأیید کنید که یک متغیر مقداردهی شده و فایل override مطابق انتظار اعمال شده است. متغیر مقداردهینشده در این خروجی بهصورت مقداری خالی و در کنار هشدار The "X" variable is not set. Defaulting to a blank string. ظاهر میشود.
--dry-run یک پرچم سراسری است، نه پرچم یک subcommand؛ بنابراین باید پیش از up بیاید. این گزینه تمام اقدامهایی را که Compose انجام خواهد داد چاپ میکند و هیچ تغییری ایجاد نمیکند. صرف سی ثانیه برای اجرای آن پیش از down روی stack مهم، ارزش دارد.
کار با فایلها، پروفایلها و پروژهها
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dچند پرچم -f بهترتیب با هم ادغام میشوند و فایلهای بعدی، هر کلید را جداگانه در فایلهای قبلی بازنویسی میکنند. روش استاندارد این است که یک فایل پایه را با یک بازنویسی کوچک برای محیط production نگه دارید. بااینحال، قوانین ادغام برای فهرستها و mapها متفاوت است؛ بنابراین پیش از بررسی یک نتیجه غیرمنتظره، نحوه ادغام چند فایل Compose را مطالعه کنید.
--profile سرویسهایی را که با آن profile علامتگذاری شدهاند، در کنار سرویسهای بدون profile اجرا میکند. این کار ابزارهای اشکالزدایی را از یک up معمولی خارج نگه میدارد. -p نام پروژه را تعیین میکند؛ بنابراین دو نسخه از یک stack میتوانند همزمان و در کنار یکدیگر، با networkهای جداگانه و نامهای volume جداگانه اجرا شوند. بازیابی stack پس از راهاندازی مجدد، دستوری نیست که آن را مستقیماً وارد کنید؛ بلکه unitای است که این کار را برای شما انجام میدهد و در راهاندازی stackهای Compose هنگام بوت توضیح داده شده است.
FAQ
چه چیزی جایگزین docker-compose با یک خط تیره شد؟
Compose V2 که بهصورت docker compose، با یک فاصله، اجرا میشود. این ابزار یک plugin همراه با Docker Engine است و ابزار Python مربوط به V1 دیگر در packageهای فعلی نصب نمیشود. اگر فرم دارای فاصله هیچ خروجیای چاپ نمیکند، package مربوط به docker-compose-plugin را برای distribution خود نصب کنید. اسکریپتهای قدیمی را به فرم دارای فاصله بهروزرسانی کنید و alias اضافه نکنید، زیرا V2 دارای flagهایی است که V1 نداشت.
چرا docker compose restart تغییر پیکربندی من را اعمال نمیکند؟
restart، container موجود را با همان پیکربندی اولیه متوقف و دوباره اجرا میکند و هرگز compose.yaml را دوباره نمیخواند. هر تغییری در environment variableها، portها، volumeها یا image tag به docker compose up -d نیاز دارد. این دستور هر service را با container در حال اجرای آن مقایسه میکند و موارد متفاوت را دوباره ایجاد میکند. اگر میخواهید replacement حتی بدون تغییر در فایل انجام شود، --force-recreate را اضافه کنید.
چگونه یک service را به image جدیدتر بهروزرسانی کنم؟
ابتدا docker compose pull و سپس docker compose up -d را اجرا کنید. دستور pull، image فعلی مربوط به هر tag موجود در فایل را دریافت میکند و up -d هر serviceای را که image ID آن دیگر با container مطابقت ندارد، دوباره ایجاد میکند. اجرای مستقل up -d از image موجود روی دیسک استفاده میکند. به همین دلیل stackای که روی latest ثابت شده است میتواند ماهها روی یک build قدیمی باقی بماند، بدون اینکه خطایی چاپ شود.
کدام دستورهای پاکسازی روی یک server فعال ایمن هستند؟
docker system df، docker image prune -a و docker builder prune فقط imageها و cache را حذف میکنند؛ بنابراین serviceهای در حال اجرا به کار خود ادامه میدهند و named volumeها دستنخورده باقی میمانند. جفت خطرناک docker compose down -v و docker volume prune است، زیرا named volumeها را بدون درخواست تأیید حذف میکند. ابتدا docker compose config --volumes را اجرا کنید تا بدانید چه مواردی در معرض خطر هستند.
آیا میتوانم یک command را بدون راهاندازی کل stack اجرا کنم؟
بله. docker compose run --rm --no-deps web sh یک container را از service definition مربوط به web اجرا میکند، dependencyهای آن را نادیده میگیرد و پس از خروج شما container را حذف میکند. اگر container از قبل در حال اجراست، بهجای آن از exec استفاده کنید، زیرا exec به process فعال متصل میشود و وضعیت واقعی service را نشان میدهد.