Restart Policy مشخص میکند Docker پس از خروج process اصلی یا راهاندازی دوباره daemon با container چه کند. این policy میتواند سرویس را پس از crash موقت برگرداند، اما علت crash را رفع نمیکند و high availability نمیسازد. انتخاب always برای همهچیز ممکن است job تمامشده را دوباره اجرا یا crash loop را پنهان کند.
پاسخ سریع: برای سرویس دائمی، unless-stopped یا always بسته به رفتار موردنظر پس از توقف دستی انتخاب میشود؛ برای processی که فقط در خطا باید تکرار شود، on-failure با سقف retry مناسب است؛ job یکباره موفق معمولاً no میخواهد. قبل از انتخاب، exit code، idempotency، dependency و monitoring را طراحی کنید.
Policy روی چه رویدادی عمل میکند؟
مبنای اصلی خروج container است؛ یعنی PID اصلی پایان یافته است. policy تصمیم میگیرد daemon آن container را دوباره شروع کند یا نه. unhealthy شدن در حالی که PID زنده است خروج محسوب نمیشود. restart شدن daemon نیز برای بعضی policyها اهمیت دارد. رفتار Swarm service یا orchestrator دیگر را با restart policy container معمولی یکی ندانید.
no: پیشفرض و مناسب Jobهای کنترلشده
در این حالت Docker پس از exit خودکار container را شروع نمیکند. برای migration، backup یا jobی که scheduler بیرونی مالک اجرای آن است منطقی است. اگر job شکست خورد، scheduler/alert باید تصمیم retry را بگیرد. نبود restart بدون monitoring یعنی failure خاموش؛ exit code و نتیجه خروجی را ثبت کنید.
on-failure[:max-retries]
فقط exit code غیرصفر باعث restart میشود و میتوان حداکثر تلاش تعیین کرد. اگر برنامه در خطای واقعی با کد صفر خارج شود، policy آن را شکست نمیبیند. اگر job اثر جانبی دارد، retry باید idempotent باشد؛ مثلاً پرداخت یا ارسال پیام نباید دوبار انجام شود. این policy طبق مستندات برای restart خود daemon رفتار always را ندارد.
always
برای daemon طولانیعمر که باید پس از exit و بازگشت Docker بالا بیاید مناسب است. توقف دستی مانع restart فوری میشود، اما پس از restart daemon یا start دستی رفتار ادامه مییابد. سرویس باید shutdown عمدی را درست گزارش کند و داده نیمهتمام را مدیریت کند. استفاده برای containerی که کارش تمام میشود، اجرای بیپایان میسازد.
unless-stopped
شبیه always است، اما containerی که متوقف شده، پس از restart daemon هم خودکار بالا نمیآید. برای محیطی که توقف دستی باید ماندگار باشد مفید است. این گزینه جای ثبت maintenance نیست؛ تیم باید بداند چه کسی و چرا سرویس را stop کرده و چه زمانی باید برگردد.
جدول تصمیم عملی
- سرویس وب دائمی: معمولاً always یا unless-stopped همراه health و alert.
- Worker دائمی: policy دائمی، اما jobها idempotent و shutdown graceful.
- Migration یکباره: no؛ موفقیت و failure توسط deployment کنترل شود.
- Batch قابل retry: on-failure با سقف و backoff در برنامه.
- ابزار تعاملی: معمولاً no تا exit کاربر محترم بماند.
این جدول نقطه شروع است، نه قانون ثابت. SLA، scheduler و orchestrator واقعی را در نظر بگیرید.
نمونه Compose
services:
app:
image: registry.example/app@sha256:...
restart: unless-stopped
گزینه restart در Compose معمول با deploy.restart_policy در مدلهای orchestration یکسان نیست. فایل نهایی Compose و نسخه ابزار را بررسی کنید. digest نمونه را با artifact واقعی جایگزین کنید. تغییر config ممکن است نیازمند recreate باشد؛ پس rollout و rollback را آماده کنید.
شرط «شروع موفق»
Docker برای فعالشدن کامل restart policy، شروع موفق container را در نظر میگیرد؛ مستندات Engine آن را حدود ده ثانیه اجرای پایدار توضیح میدهند. این رفتار جلوی بعضی loopهای آغاز فوری را میگیرد، اما تضمین نمیکند برنامه سالم است. startup سریع و crash پس از آن همچنان میتواند بارها تکرار شود. healthcheck و log لازماند.
توقف دستی چه میکند؟
وقتی اپراتور container را دستی stop میکند، policy برای جلوگیری از جنگ با اپراتور نادیده گرفته میشود تا container دوباره دستی start شود یا daemon طبق semantics policy تغییر کند. تفاوت always و unless-stopped در بازگشت پس از daemon restart مهم است. این رفتار را در runbook maintenance و بعد از reboot تست کنید.
Exit Code قرارداد مهم برنامه است
صفر یعنی پایان موفق و غیرصفر شکست است. wrapper script نباید خطای child را با exit صفر بپوشاند. shell entrypoint باید signal را forward و در نهایت کد درست را برگرداند. اگر process با OOM یا signal کشته شود، State و exit code را inspect کنید. یک policy مناسب بدون exit code صادق تصمیم اشتباه میگیرد.
Restart Policy و Healthcheck
این دو مکملاند اما بهطور پیشفرض اتصال خودکار ندارند. Healthcheck میتواند container running را unhealthy اعلام کند، در حالی که restart policy فقط منتظر exit است. راهنمای Healthcheck توضیح میدهد چگونه نتیجه probe را بدون restart آبشاری مصرف کنید. اگر automation سفارشی میسازید، cooldown، سقف تلاش و alert داشته باشد.
Restart با Recovery فرق دارد
اگر dependency قطع، migration ناقص، secret اشتباه یا Disk پر باشد، restart مکرر مشکل را تشدید میکند. برنامه باید retry محدود و backoff داشته باشد و operator signal واضح بگیرد. برای corruption یا ناسازگاری schema، توقف و بررسی امنتر از تلاش بینهایت است. policy نباید شکست دائمی را به چرخه خاموش تبدیل کند.
Backoff و سقف تلاش را در کدام لایه بگذاریم؟
Docker برای restartهای متوالی رفتار تأخیری دارد، اما برنامه نباید منطق retry عملیات تجاری را به restart process واگذار کند. اتصال موقت dependency میتواند داخل برنامه با timeout، backoff و jitter مدیریت شود؛ شکست startup دائمی باید با exit و alert روشن متوقف شود. برای job اثرگذار، scheduler باید تعداد تلاش و idempotency را بداند. چند لایه retry روی هم میتوانند تعداد درخواست را انفجاری کنند، پس بودجه تلاش را end-to-end حساب کنید.
restart: true در depends_on همان Restart Policy نیست
در Compose جدید، گزینه restart در dependency میتواند هنگام عملیات صریح Compose روی dependency، سرویس وابسته را نیز restart کند. این با کلید سطح سرویس restart: unless-stopped متفاوت است. یکی رابطه عملیات Compose را بیان میکند و دیگری رفتار container پس از exit/daemon restart را. خروجی config نهایی را بخوانید و نام یکسان «restart» را به رفتار یکسان تعبیر نکنید.
داده و کار نیمهتمام
Worker باید قبل از exit job را acknowledge نکند یا بتواند آن را دوباره ایمن اجرا کند. وبسرور باید SIGTERM را بگیرد و requestهای جاری را در grace period جمع کند. دیتابیس نیازمند shutdown و storage معتبر است. Restart Policy هیچکدام را خودکار نمیسازد؛ فقط process را دوباره شروع میکند.
مانیتور چه چیزهایی باشد؟
restart count، زمان آخرین exit، exit code، OOMKilled، uptime کوتاه، health و latency کاربر را پایش کنید. سرویسی که هر دقیقه restart و سریع برمیگردد ممکن است در availability ساده سبز دیده شود. eventهای Docker را با deploy و تغییر config مرتبط کنید. هشدار باید پیش از مصرف تمام CPU/Disk توسط loop فعال شود.
تغییر Policy روی Container موجود
Docker امکان update policy را دارد، اما در پروژه Compose بهتر است منبع تعریف را هم اصلاح کنید تا recreate بعدی تنظیم را برنگرداند. تغییر فوری در daemon فقط میتواند remediation موقت باشد؛ drift میان config و runtime را ثبت و رفع کنید. قبل از تغییر گروهی، سرویسهای batch و maintenance را از daemonها جدا کنید.
اشتباههای رایج
- قرار دادن always روی migration و job موفق
- اتکا به restart بهجای رفع crash
- نبود سقف retry برای عملیات اثرگذار
- پوشاندن exit code در entrypoint
- فرض اینکه unhealthy خودکار restart میشود
- ندیدن OOM و Disk در crash loop
- تغییر دستی runtime بدون اصلاح Compose
چه زمانی طراحی را بازبینی کنیم؟
اگر سرویس مرتب restart میشود یا بعد از reboot رفتار غیرمنتظره دارد، policy فقط یک علامت از قرارداد ناقص lifecycle است. داکرایز اپلیکیشن میتواند exit، signal، health و policy را با نوع workload هماهنگ کند. برای crash فعال، راهنمای Restart Loop را دنبال کنید.
پرسشهای متداول
always و unless-stopped چه تفاوتی دارند؟
پس از توقف دستی و restart daemon، unless-stopped متوقف میماند؛ always طبق semantics خود دوباره بالا میآید.
on-failure برای exit صفر چه میکند؟
آن را موفق میداند و restart نمیکند.
آیا Restart Policy جای process manager داخل container است؟
برای PID اصلی معمولاً Docker policy کافی است؛ چند process نیازمند طراحی lifecycle و signal روشناند.
آیا restart count بالا طبیعی است؟
در deploy کنترلشده ممکن است کمی تغییر کند، اما رشد مداوم نشانه failure یا policy نامناسب است.