Docker

शेड्यूल किए गए कंटेनर जॉब्स, और उनके लिए Kubernetes अपनाए बिना।

अगर आपकी टीम Docker चलाती है पर Kubernetes नहीं, तो शेड्यूल किए गए कंटेनर जॉब के लिए कोई अच्छी जगह ही नहीं है। Dagu एक single binary है जो आपके मौजूदा Docker डेमन को चलाता है और कंटेनरों के चारों ओर निर्भरता, पुनःप्रयास, लॉग और वेब UI जोड़ता है।

न Kubernetes चाहिए, न कोई कंटेनर प्लेटफ़ॉर्म
चरण एक ही कंटेनर साझा करें, या हर चरण अपनी image लाए
compose से पहले से चल रहे कंटेनरों में exec करें
Podman उसी Docker-संगत API से काम करता है
01

docker run और Kubernetes CronJob के बीच की खाली जगह

कंटेनर को शेड्यूल करना वही बिंदु है जहाँ अच्छे विकल्प समाप्त हो जाते हैं। Kubernetes CronJob परिपक्व उत्तर है, पर तभी जब क्लस्टर पहले से हो। उससे नीचे सामान्य उत्तर है cron जो docker run बुलाता है, और उसके अलावा कुछ नहीं देता।

  • cron और docker run मिलकर न पुनःप्रयास देते हैं, न जॉब्स के बीच निर्भरता, न रन इतिहास, न यह देखने का तरीका कि कल रात क्यों विफल हुआ
  • एक रात्रिकालीन रिपोर्ट शेड्यूल करने के लिए Kubernetes अपनाना, छोटे से जॉब के लिए बहुत बड़ा प्लेटफ़ॉर्म है
  • एक सामान्य ऑर्केस्ट्रेटर जो कंटेनर को तैनाती का लक्ष्य नहीं बल्कि एक चरण-प्रकार मानता है, ठीक इसी बीच में बैठता है
02

पूरे वर्कफ़्लो के लिए एक कंटेनर

वर्कफ़्लो स्तर पर कंटेनर घोषित करने से सभी चरण एक ही दीर्घजीवी कंटेनर के भीतर चलते हैं। वे फ़ाइल सिस्टम साझा करते हैं, इसलिए एक चरण द्वारा इंस्टॉल किए पैकेज अगले चरण में भी मौजूद रहते हैं।

  • निर्भरताएँ एक बार इंस्टॉल करके चरणों में दोबारा उपयोग करें, image दोबारा बनाए या हर टास्क पर दोबारा इंस्टॉल किए बिना
  • volumes से होस्ट पथ माउंट करें और पर्यावरण चर पूरे वर्कफ़्लो के लिए एक बार सेट करें
  • पुनःप्रयास, निर्भरता और विफलता प्रबंधन सामान्य वर्कफ़्लो फ़ील्ड ही रहते हैं, चाहे चरण कंटेनर में चलें

इस मोड में चरण docker exec के ज़रिए चलते हैं, इसलिए image का ENTRYPOINT और CMD चरण की कमांड के लिए उपयोग नहीं होते। कमांड चरण में लिखें।

पूरी तरह एक image के भीतर चलने वाला रात्रिकालीन जॉब
# nightly-report.yaml
schedule: "0 3 * * *"
max_active_runs: 1

container:
  image: python:3.12
  volumes:
    - ./data:/data
  env:
    - TZ=Asia/Tokyo

steps:
  - id: install
    run: pip install -r /data/requirements.txt

  - id: build_report
    run: python /data/build_report.py
    depends: install
    retry_policy:
      limit: 2
      interval_sec: 120

  - id: publish
    run: python /data/publish.py
    depends: build_report

mail_on:
  failure: true
03

पहले से चल रहे कंटेनरों में रखरखाव चलाएँ

exec मोड वर्कफ़्लो को पहले से चल रहे कंटेनर की ओर इंगित करता है, जैसे Docker Compose से शुरू किया गया कंटेनर। निर्धारित काम असली चल रहे एप्लिकेशन कंटेनर के भीतर होता है, उसकी नई प्रति में नहीं।

  • डेटाबेस माइग्रेशन, कैश क्लियर और क्यू रखरखाव वास्तव में चल रही सेवा पर चलते हैं
  • कॉन्फ़िगरेशन बस कंटेनर का नाम स्ट्रिंग के रूप में लिखना है
  • वर्कफ़्लो को निर्भरता और विफलता सूचना मिलती रहती है, जिन्हें compose फ़ाइल व्यक्त नहीं कर सकती
चल रही compose सेवा पर निर्धारित रखरखाव
# app-maintenance.yaml
schedule: "0 4 * * *"
max_active_runs: 1

# docker compose で起動済みのコンテナに exec する
container: myapp-web

steps:
  - id: migrate
    run: php artisan migrate --force

  - id: prune_sessions
    run: php artisan session:prune
    depends: migrate

  - id: clear_cache
    run: php artisan cache:clear
    depends: prune_sessions

mail_on:
  failure: true
04

हर चरण के लिए अलग image

जब पाइपलाइन कई उपकरणों से गुज़रती है, हर चरण अपनी image ला सकता है। वर्कफ़्लो एक ही फ़ाइल और एक ही शेड्यूल रहता है जबकि चरण स्वतंत्र बने रहते हैं।

  • डेटाबेस क्लाइंट image से निकालें, भाषा image से रूपांतरित करें, दूसरे क्लाइंट से लोड करें, बिना ऐसी image के जिसमें तीनों हों
  • चरण स्तर का कंटेनर वर्कफ़्लो स्तर वाले को ओवरराइड करता है, इसलिए लगभग एकरूप वर्कफ़्लो में भी अपवाद बन सकते हैं
  • image pull नीति प्रति चरण सेट होती है, स्थिर और बार-बार बनने वाली दोनों तरह की images के लिए
एक वर्कफ़्लो, तीन images
# etl-pipeline.yaml
schedule: "0 2 * * *"
max_active_runs: 1

steps:
  - id: extract
    container:
      image: mysql:8
      volumes:
        - ./work:/work
    run: mysqldump --host db.internal -u svc app > /work/dump.sql

  - id: transform
    container:
      image: python:3.12
      volumes:
        - ./work:/work
    run: python /work/transform.py
    depends: extract

  - id: load
    container:
      image: postgres:16
      volumes:
        - ./work:/work
    run: psql -h dw.internal -f /work/out.sql
    depends: transform

handler_on:
  failure:
    run: ./scripts/notify-failure.sh

mail_on:
  failure: true
05

होस्ट से क्या चाहिए

कंटेनर चरण एक Docker-संगत API से बात करते हैं। यही एकमात्र आवश्यकता है, और तैनाती की योजना बनाने से पहले जानने योग्य बाध्यता भी।

  • स्थानीय Docker सॉकेट और DOCKER_HOST से जुड़ा दूरस्थ डेमन, दोनों काम करते हैं
  • DAGU_CONTAINER_RUNTIME=podman सेट करके Podman के Docker-संगत API से भी काम होता है
  • चूँकि Dagu एक single binary है, शेड्यूलर को स्वयं न क्लस्टर चाहिए, न मेटाडेटा डेटाबेस, न ब्रोकर

Dagu Cloud की प्रबंधित इंस्टेंस gVisor आइसोलेशन के साथ चलती हैं और कंटेनर डेमन सॉकेट उजागर नहीं करतीं, इसलिए वहाँ कंटेनर चरण उपलब्ध नहीं हैं। सेल्फ-होस्टेड Dagu उपयोग करें, या वर्कफ़्लो को सेल्फ-होस्टेड worker पर भेजें।

06

जहाँ Kubernetes ही सही उत्तर है

यह पृष्ठ एक विशेष स्थिति में छोटे उपकरण की वकालत करता है, न कि आम तौर पर Kubernetes से बचने की।

  • यदि आप पहले से क्लस्टर चला रहे हैं, तो CronJob निर्धारित कंटेनरों के लिए उचित जगह है और कुछ नया नहीं चाहिए
  • यदि जॉब्स को pod स्तर की शेड्यूलिंग, ऑटोस्केलिंग या नोड्स में bin-packing चाहिए, वह क्लस्टर का काम है, ऑर्केस्ट्रेटर का नहीं
  • जो वर्कफ़्लो ऑर्केस्ट्रेशन क्लस्टर के बाहर रखते हुए काम क्लस्टर को भेजना चाहते हैं, उनके लिए Dagu में Kubernetes चरण है

FAQ

Practical questions before adopting

निर्धारित कंटेनर जॉब चलाने के लिए क्या Kubernetes चाहिए?

नहीं। Dagu सीधे Docker-संगत डेमन से बात करता है, इसलिए Docker वाला एक होस्ट पर्याप्त है। Kubernetes तब सार्थक होता है जब क्लस्टर स्तर की शेड्यूलिंग और स्केलिंग चाहिए, केवल रात तीन बजे एक कंटेनर चलाने के लिए नहीं।

यह Airflow के Docker operator से कैसे अलग है?

मुख्य रूप से संचालन लागत में। Airflow को एक कंटेनर चलाने से पहले शेड्यूलर, मेटाडेटा डेटाबेस और Python DAG फ़्रेमवर्क चाहिए। Dagu फ़ाइल-आधारित स्थिति वाला single binary है, और कंटेनर Python operator के बजाय वर्कफ़्लो या चरण का एक फ़ील्ड है।

क्या चरण आपस में फ़ाइलें साझा कर सकते हैं?

हाँ। वर्कफ़्लो स्तर के कंटेनर के साथ चरण एक ही कंटेनर में चलते हैं और उसका फ़ाइल सिस्टम सीधे साझा करते हैं। प्रति चरण अलग images होने पर, हर चरण में एक साझा होस्ट पथ माउंट करें।

क्या Podman काम करता है?

हाँ, Podman के Docker-संगत API से। सेल्फ-होस्टेड परिनियोजन में DAGU_CONTAINER_RUNTIME=podman सेट करें, कंटेनर चरण उसी तरह व्यवहार करते हैं।

क्या मैं Docker Compose से शुरू किए कंटेनर के भीतर चरण चला सकता हूँ?

हाँ, वही exec मोड है। चल रहे कंटेनर का नाम दें और वर्कफ़्लो के चरण उसी में चलेंगे। चालू compose स्टैक पर निर्धारित माइग्रेशन और कैश रखरखाव आम तौर पर इसी तरह जोड़े जाते हैं।

Next step

Start with one workflow.

Install Dagu, move one script that runs on cron today into YAML, and decide from a real run history.