सॉफ्टवेयर को कंटेनराइज़ करना इसे विकास और तैनाती में आसानी के लिए मानकीकृत इकाइयों में पैकेजिंग करना है। कंटेनर आपके एप्लिकेशन से कोड को उसकी सभी निर्भरताओं के साथ बंडल करते हैं। एक कंटेनर पूरी तरह से अकेला खड़ा हो सकता है; इसमें आपके सॉफ्टवेयर, एक रनटाइम वातावरण, और सिस्टम लाइब्रेरी के साथ एक पैकेज होता है। कंटेनर डेवलपर्स और ऑपरेशन टीमों को यह सुनिश्चित करने में मदद करते हैं कि सॉफ्टवेयर अपने वातावरण की परवाह किए बिना समान रूप से चलता है। कोड को इन्फ्रास्ट्रक्चर से अलग करके, "कंटेनराइज़्ड" ऐप्स स्थानीय वातावरण, एक टेस्ट वातावरण, और प्रोडक्शन में समान रूप से चलते हैं।
Docker सॉफ्टवेयर विकसित करने और तैनात करने के लिए सबसे लोकप्रिय प्लेटफार्मों में से एक है। Docker सॉफ्टवेयर को एक "इमेज" के रूप में पैकेज करता है, जिसे रनटाइम पर Docker इमेज पर निष्पादित होने पर एक कंटेनर में बदल दिया जाता है। अलगाव डेवलपर्स को एक ही होस्ट पर एक ही समय में कई कंटेनर चलाने की अनुमति देता है।
Rails डेवलपर्स को मौजूदा एप्लिकेशन को कंटेनराइज़ करते समय चुनौतियों का एक अनूठा सेट का सामना करना पड़ता है। यह लेख एक कार्यात्मक Rails ऐप को कंटेनराइज़ करने का एक वॉकथ्रू प्रदान करेगा और रास्ते में महत्वपूर्ण अवधारणाओं और नुकसानों को समझाएगा। यह लेख कंटेनर या Docker का बुनियादी विवरण नहीं है; बल्कि, यह उन समस्याओं की व्याख्या है जिनका सामना डेवलपर्स प्रोडक्शन एप्लिकेशन को कंटेनराइज़ करते समय करते हैं।
पूर्वापेक्षाएँ
यदि आप साथ चल रहे हैं, तो आपको स्पष्ट रूप से एक Rails एप्लिकेशन की आवश्यकता होगी जो पहले से डॉकराइज़्ड नहीं है (यह 'कंटेनराइज़्ड' के लिए Docker-विशिष्ट शब्द है)। मैं RailsWork का उपयोग करूंगा, एक पूर्ण विशेषताओं वाला साइड प्रोजेक्ट जिसे मैंने अभी लॉन्च किया है। यह Rails के साथ लिखा गया एक जॉब-बोर्ड है और Heroku पर तैनात है, लेकिन यह कंटेनराइज़्ड नहीं है।
इसके अलावा, आपको Docker इंस्टॉल करने की भी आवश्यकता होगी। इसे इंस्टॉल करने का एक लोकप्रिय तरीका Docker Desktop के साथ है, जिसे आधिकारिक वेबसाइट के माध्यम से डाउनलोड किया जा सकता है।

एक बार ऐप डाउनलोड हो जाने पर, इंस्टॉलर चलाएं। इसके चलने के बाद, यह आपको एप्लिकेशन को अपने एप्लिकेशन फ़ोल्डर में खींचने के लिए प्रेरित करेगा। फिर आपको ऐप को अपने एप्लिकेशन फ़ोल्डर से लॉन्च करना होगा और इसे अनुरोधित विशेषाधिकारों को प्रदान करना होगा। यह सुनिश्चित करने के लिए अंतिम जांच के रूप में कि Docker सही ढंग से इंस्टॉल है, अपने टर्मिनल से अपनी मशीन पर चल रहे कंटेनरों को सूचीबद्ध करने का प्रयास करें निम्नलिखित चलाकर:
docker ps
यदि Docker इंस्टॉल है (और आप कोई कंटेनर नहीं चला रहे हैं), तो आपको केवल हेडर के साथ एक खाली सूची मिलेगी जो इस तरह दिखती है:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Dockerfile
इससे पहले कि हम बहुत गहरे में गोता लगाएँ, स्पष्ट शब्दावली के साथ शुरू करना महत्वपूर्ण है।
आपके Rails एप्लिकेशन के "Dockerized" होने के बाद, यह एक कंटेनर में चलेगा। एक कंटेनर अकेला खड़ा होता है, बदला जा सकता है, और अक्सर पुनर्निर्मित किया जाता है।
एक कंटेनर एक इमेज से बनाया जाता है। एक इमेज मेटाडेटा के साथ जोड़ी गई एक फाइल सिस्टम का एक वर्चुअल स्नैपशॉट है।
एक Dockerfile सोर्स कोड है जो वर्णन करता है कि एक इमेज कैसे बनाई जानी चाहिए। Dockerfiles को अक्सर एक Dockerized ऐप के रिपॉजिटरी में शामिल किया जाता है और बाकी ऐप के साथ वर्जन कंट्रोल में ट्रैक किया जाता है।
Dockerfile बनाना जितना लगता है उससे कहीं आसान है! Docker हमें विशेष सिंटैक्स देता है जो किसी चीज़ को कंटेनराइज़ करने के कठिन काम को सार करता है। सबसे पहले, उस ऐप के रूट डायरेक्टरी पर जाएं जिसे आप कंटेनराइज़ करना चाहते हैं। अब जब आप काम शुरू करने के लिए तैयार हैं, तो यदि आप Git का उपयोग कर रहे हैं तो एक नई ब्रांच बनाना एक अच्छा विचार है। आप निम्नलिखित चलाकर dockerize-this-app नाम से आसानी से एक नई ब्रांच बना सकते हैं:
git checkout -b dockerize-this-app
अब, एक Dockerfile बनाएं और इसे Ruby एप्लिकेशन के आधार पर एक इमेज बनाने के लिए निर्देशित करें। यह कमांड लाइन से निम्नलिखित चलाकर किया जा सकता है:
echo "FROM ruby:3.0.0" > Dockerfile
यहां, हम सिर्फ Dockerfile बना रहे हैं और एक पंक्ति जोड़ रहे हैं जो यह निर्दिष्ट करती है कि Ruby कंटेनर इमेज कहां मिलेगी। मेरा प्रोजेक्ट Ruby 3.0.0 का उपयोग करता है, इसलिए मैंने उपयुक्त इमेज का उपयोग किया। यदि आप Ruby के एक अलग संस्करण पर हैं, तो यह कोई समस्या नहीं है। Docker में सभी समर्थित इमेज की सूची है।
अब, Docker को मैन्युअली Docker इमेज बनाने का निर्देश दें:
docker build -t rails_work .
यहां, आप rails_work को इमेज के लिए किसी भी नाम से बदल सकते हैं जो आप चाहें। साथ ही, अंत में पीरियड शामिल करना सुनिश्चित करें!
यदि आप देखना चाहते हैं कि इमेज बनाई गई है, तो आप निम्नलिखित के साथ अपने सिस्टम पर इमेज सूचीबद्ध कर सकते हैं:
docker image list
यह इमेज ज्यादातर खाली है, हालांकि; इसमें वर्तमान में हमारा एप्लिकेशन नहीं है। हम इसे अपने ऐप से कोड जोड़ने का निर्देश दे सकते हैं Dockerfile के अंत में निम्नलिखित जोड़कर:
ADD . /rails_work WORKDIR /rails_work RUN bundle install
यह आपके एप्लिकेशन से फाइलों को कॉपी करता है और एप्लिकेशन की निर्भरताओं को इंस्टॉल करता है। (यहां, आप rails_work को अपने ऐप के नाम से बदलेंगे।)
इस बिंदु पर, आपको इमेज बनाने के लिए कमांड को फिर से चलाना चाहिए:
docker image list
यहां एक समस्या की संभावना है, खासकर यदि आप इसे मौजूदा प्रोडक्शन एप्लिकेशन पर कर रहे हैं। Bundler शिकायत कर सकता है कि इमेज जिस Bundler संस्करण का उपयोग करने का प्रयास कर रही है, वह उस संस्करण से अलग है जिसने Gemfile.lock फ़ाइल बनाई थी। यदि ऐसा होता है, तो आपके पास दो स्पष्ट विकल्प हैं:
- इमेज द्वारा उपयोग किए जा रहे संस्करण को बदलें।
Gemfile.lockको पूरी तरह से हटा दें। **यदि आप ऐसा करते हैं, तो सुनिश्चित करें कि आप जिन जेम्स के विशिष्ट संस्करणों की आवश्यकता है, उन्हें पिन करें, क्योंकि लॉकफाइल पूरी तरह से पुनर्जनरेट हो जाएगी।
यदि आपका bundle install अभी भी विफल होता है, तो आपको अपने Dockerfile में कुछ अतिरिक्त इंस्टॉलेशन की आवश्यकता हो सकती है:
RUN apt-get update && apt-get install -y shared-mime-info
यदि आप अभी भी समस्याओं का सामना कर रहे हैं, तो आपने Ruby इमेज को आधार बनाने के लिए गलत चुना होगा, इसलिए वहां जांच शुरू करना उचित है।
यहां पर्यावरण चर सेट करने का एक अच्छा अवसर है:
ENV RAILS_ENV production ENV RAILS_SERVE_STATIC_FILES true
इसके बाद, पोर्ट 3000 को उजागर करने के लिए एक पंक्ति जोड़ें, जो वह जगह है जहां Rails डिफ़ॉल्ट रूप से चलता है:
EXPOSE 3000
अंत में, कंटेनर को शुरू होने पर एक bash शेल खोलने का निर्देश दें:
CMD ["bash"]
कुल मिलाकर, आपका Dockerfile इस तरह दिखना चाहिए (rails_work नाम को प्रतिस्थापित करके):
FROM ruby:3.0.0 ADD . /rails_work WORKDIR /rails_work RUN bundle install ENV RAILS_ENV production ENV RAILS_SERVE_STATIC_FILES true EXPOSE 3000 CMD ["bash"]
Docker कमांड समझाए गए
कुछ सबसे आम Dockerfile कमांड की पूरी समझ रखना निश्चित रूप से मदद करेगा।
- FROM -> यह परिभाषित करता है कि किस इमेज को आधार बनाना है।
- RUN -> यह कमांड को कंटेनर के अंदर निष्पादित करता है।
- ENV -> यह पर्यावरण चर को परिभाषित करता है।
- WORKDIR -> यह कंटेनर द्वारा उपयोग की जा रही डायरेक्टरी को बदलता है।
- CMD -> कंटेनर शुरू होने पर कौन सा प्रोग्राम चलाना है यह निर्दिष्ट करता है।
Docker Compose
Docker के दस्तावेज़ीकरण के अनुसार, "Compose" कई Docker कंटेनरों के साथ एप्लिकेशन बनाने (और शुरू करने) के लिए उनका टूल है। ऐप के आवश्यक कंटेनरों को स्पिन अप करने के लिए आवश्यक सब कुछ YAML में उल्लिखित है। जब कोई docker-compose up चलाता है, तो कंटेनर बनाए जाते हैं! Docker-compose हमें हमारे कंटेनर कॉन्फ़िगरेशन को घोषणात्मक रूप से वर्णन करने देता है।
अपना Docker Compose फ़ाइल बनाने से पहले, यह इंगित करना महत्वपूर्ण है कि Docker को कौन सी फ़ाइलों को बनाई जाने वाली इमेज से बाहर रखा जाना चाहिए। .dockerignore नामक एक फ़ाइल बनाएं। (पीरियड नोट करें!) इस फ़ाइल में, निम्नलिखित पेस्ट करें:
.git .dockerignore .env
यदि आपका Gemfile बिल्ड प्रक्रिया द्वारा बनाए रखा जाता है, तो उपरोक्त अनदेखी में Gemfile.lock जोड़ना सुनिश्चित करें।
अब, docker-compose.yml नामक एक फ़ाइल बनाएं। यह वह जगह है जहां हम अपने कंटेनर कॉन्फ़िगरेशन का वर्णन करेंगे। हम फ़ाइल की सामग्री के लिए इससे शुरू करेंगे:
version: '3.8' services: db: image: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password volumes: - postgres:/var/lib/postgresql/data web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/Rails-Docker ports: - "3000:3000" depends_on: - db volumes: postgres:
यह फ़ाइल दो सेवाएं बनाती है: एक जिसे db कहा जाता है और दूसरी जिसे web कहा जाता है। db कंटेनर postgres के लिए अभिप्रेत एक पूर्वनिर्मित इमेज से बनाया जाएगा, और आपको POSTGRES_USER और POSTGRES_PASSWORD के लिए प्रासंगिक मान प्रतिस्थापित करने चाहिए। आपको इस फ़ाइल में प्रोडक्शन सीक्रेट नहीं डालने चाहिए - इस पर अधिक जानकारी के लिए नीचे "सीक्रेट्स प्रबंधित करना" अनुभाग देखें।
web कंटेनर हमारे Dockerfile से बनाया गया है और फिर पोर्ट 3000 पर IP एड्रेस 0.0.0.0 पर एक Rails सर्वर शुरू करता है। आंतरिक पोर्ट 3000 को फिर वास्तविक पोर्ट 3000 पर मैप किया जाता है।
और अंत में, हमारे पास हमारे लिए डेटा को बनाए रखने के लिए एक Postgres वॉल्यूम है।
सीक्रेट्स प्रबंधित करना
बिल्ड-टाइम पर प्रमाणीकरण प्रोडक्शन एप्लिकेशन के लिए एक मुद्दा हो सकता है। शायद आपका एप्लिकेशन एक निजी रिपॉजिटरी से जेम्स चाहता है, या आपको बस डेटाबेस क्रेडेंशियल्स स्टोर करने की आवश्यकता है।
Dockerfile में सीधे मौजूद कोई भी जानकारी हमेशा के लिए कंटेनर इमेज में बेक हो जाती है, और यह एक आम सुरक्षा गड्ढा है।
यदि आप Rails के क्रेडेंशियल मैनेजर का उपयोग कर रहे हैं, तो Docker (या उस मामले के लिए कोई भी होस्ट) को एक्सेस देना अपेक्षाकृत तुच्छ है। Docker Compose फ़ाइल में, आप बस RAILS_MASTER_KEY पर्यावरण चर प्रदान करते हैं। दिए गए Compose टारगेट के लिए, आप environment हेडर के तहत कुंजी निर्दिष्ट करते हैं, जिसे आपको बनाने की आवश्यकता है यदि आपने पहले से नहीं बनाया है। ऊपर से docker-compose फ़ाइल तब निम्नलिखित बन जाएगी:
version: '3.8' services: db: image: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password volumes: - postgres:/var/lib/postgresql/data web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/Rails-Docker ports: - "3000:3000" depends_on: - db environment: - RAILS_MASTER_KEY=this_would_be_the_key volumes: postgres:
अब, यह आपको एक चौराहे पर छोड़ देता है। आप संभवतः इस फ़ाइल को सोर्स कंट्रोल में कमिट करना चाहेंगे, लेकिन आप निश्चित रूप से अपने मास्टर कुंजी या यहां तक कि अपने डेटाबेस पासवर्ड को सोर्स कंट्रोल द्वारा ट्रैक नहीं करना चाहते, क्योंकि यह एक और खतरनाक सुरक्षा मुद्दा होगा। अब तक का सबसे अच्छा समाधान dotenv जेम का उपयोग करना होगा ताकि आप इन क्रेडेंशियल्स को प्रॉक्सी द्वारा एक्सेस कर सकें, उन्हें एक अलग फ़ाइल में संग्रहीत कर सकें जिसे सोर्स कंट्रोल द्वारा ट्रैक नहीं किया जाता है।
Dockerized एप्लिकेशन चलाना
अंत में, आप निम्नलिखित कमांड के साथ Dockerized एप्लिकेशन चला सकते हैं:
docker compose up
मानो या न मानो, बस इतना ही है! Docker-compose कंटेनर को स्पिन अप करना आसान बनाता है, खासकर जब कमांड-लाइन आर्गुमेंट की बात आती है।
यदि आप चल रहे कंटेनरों की सूची चाहते हैं, तो बस निम्नलिखित चलाएं:
docker ps
यदि आपका Rails कंटेनर नाम web है, तो आप इस पर कमांड को काफी सीधे तरीके से निष्पादित कर सकते हैं। उदाहरण के लिए, यदि आप Rails कंसोल चलाना चाहते हैं, तो आपको बस निम्नलिखित चलाने की आवश्यकता है:
docker exec -it web rails console
यदि आप कंटेनर के अंदर सिर्फ एक bash शेल चाहते हैं, तो आप इसके बजाय निम्नलिखित चलाएंगे:
docker exec -it web bash
यहां सूचीबद्ध जैसे कुछ और नुकसान
प्रोडक्शन में Dockerized Rails एप्लिकेशन के साथ एक आम मुद्दा लॉग से निपटना है। उन्हें लंबी अवधि के लिए कंटेनर सिस्टम में नहीं होना चाहिए। Docker सुझाव देता है कि लॉग को केवल STDOUT पर रीडायरेक्ट किया जाए। इसे config/application.rb में स्पष्ट रूप से कॉन्फ़िगर किया जा सकता है।
एक और आम मुद्दा मेलर्स का है। यदि आपका एप्लिकेशन मेलर्स का उपयोग करता है, आपको कनेक्शन सेटिंग्स को स्पष्ट रूप से परिभाषित करना होगा। SMTP एक पूरी तरह से ठीक डिलीवरी विधि है और आमतौर पर डिफ़ॉल्ट के साथ अच्छी तरह से काम करती है, लेकिन हमें सर्वर स्थान और अन्य सेटिंग्स को हमारे कंटेनर कॉन्फ़िगरेशन से मेल खाने के लिए सावधान रहना चाहिए।
यदि आपके पास वर्कर्स या बैकग्राउंड जॉब्स हैं, जैसे Sidekiq, तो आपको इसे अपने स्वयं के कंटेनर में चलाना होगा।
निष्कर्ष
प्रोडक्शन Rails एप्लिकेशन को कंटेनराइज़ करना चुनौतियों के एक सेट के साथ आता है, जैसा कि आपने निस्संदेह देखा है। जैसे-जैसे आपका एप्लिकेशन बढ़ा है, इसने कई निर्भरताओं को जमा किया है जो इस तरह के माइग्रेशन को चुनौतीपूर्ण बनाते हैं। चाहे वह बैकग्राउंड वर्कर्स, मेलर्स, या सीक्रेट्स हों, अधिकांश नुकसानों को संभालने के लिए स्थापित पैटर्न हैं। एक बार प्रोडक्शन एप्लिकेशन को Docker के साथ काम करने का प्रारंभिक कार्य पूरा हो जाने पर, भविष्य के परिवर्तनों और डिप्लॉयमेंट की आसानी निवेश को सार्थक बना देगी।