फ़ाइल परिवर्तनों पर डॉकटर कंटेनर का पुनर्निर्माण करें


86

ASP.NET कोर एप्लिकेशन को चलाने के लिए, मैंने एक डॉकफाइल उत्पन्न किया जो एप्लिकेशन का निर्माण करता है और कंटेनर में स्रोत कोड को कॉपी करता है, जिसे जेनकिन्स का उपयोग करके गिट द्वारा प्राप्त किया जाता है। इसलिए अपने कार्यक्षेत्र में, मैं निम्नलिखित कार्य करता हूं:

WORKDIR /app
COPY src src

जबकि जेनकिन्स मेरे मेजबान पर फाइलों को सही तरीके से गिट के साथ अपडेट करता है, डॉकर इसे मेरी छवि पर लागू नहीं करता है।

निर्माण के लिए मेरी मूल स्क्रिप्ट:

#!/bin/bash
imageName=xx:my-image
containerName=my-container

docker build -t $imageName -f Dockerfile  .

containerRunning=$(docker inspect --format="{{ .State.Running }}" $containerName 2> /dev/null)

if [ "$containerRunning" == "true" ]; then
        docker stop $containerName
        docker start $containerName
else
        docker run -d -p 5000:5000 --name $containerName $imageName
fi

मैं अलग अलग बातें की तरह करने की कोशिश की --rmऔर --no-cacheके लिए पैरामीटर docker runहै और यह भी रोक / कंटेनर को हटाने से पहले नया एक का निर्माण है। मुझे यकीन नहीं है कि मैं यहां क्या गलत कर रहा हूं। ऐसा लगता है कि डॉकटर छवि को सही ढंग से अपडेट कर रहा है, क्योंकि कॉल के COPY src srcपरिणामस्वरूप लेयर आईडी और कैश कॉल नहीं होगी:

Step 6 : COPY src src
 ---> 382ef210d8fd

कंटेनर को अपडेट करने का अनुशंसित तरीका क्या है?

मेरा विशिष्ट परिदृश्य यह होगा: एप्लिकेशन डॉकटर कंटेनर में सर्वर पर चल रहा है। अब एप्लिकेशन के कुछ हिस्सों को अपडेट किया जाता है, उदाहरण के लिए एक फाइल को संशोधित करके। अब कंटेनर को नया संस्करण चलाना चाहिए। डॉकर एक मौजूदा कंटेनर को संशोधित करने के बजाय एक नई छवि बनाने की सलाह देता है, इसलिए मुझे लगता है कि मेरे द्वारा किए गए पुनर्निर्माण का सामान्य तरीका सही है, लेकिन कार्यान्वयन में कुछ विस्तार को सुधारना होगा।


क्या आप अपने कंटेनर बनाने के लिए आपके द्वारा बनाए गए सटीक चरणों को सूचीबद्ध कर सकते हैं, जिसमें आपकी कमांड और प्रत्येक कमांड से संपूर्ण आउटपुट शामिल हैं?
16

जवाबों:


136

कुछ शोध और परीक्षण के बाद, मैंने पाया कि मुझे डॉकटर के जीवनकाल के बारे में कुछ गलतफहमी थी। बस कंटेनर को पुनरारंभ करने से डॉकटर एक नई छवि का उपयोग नहीं करता है, जब इस बीच छवि को फिर से बनाया गया था। इसके बजाय, डॉकटर केवल कंटेनर बनाने से पहले छवि प्राप्त कर रहा है । इसलिए कंटेनर चलाने के बाद की स्थिति लगातार बनी रहती है।

क्यों हटाना आवश्यक है

इसलिए, पुनर्निर्माण और पुनः आरंभ करना पर्याप्त नहीं है। मुझे लगा कि कंटेनर एक सेवा की तरह काम करते हैं: सेवा को रोकना, अपने बदलाव करना, इसे फिर से शुरू करना और वे लागू होंगे। यही मेरी सबसे बड़ी गलती थी।

क्योंकि कंटेनर स्थायी हैं, आपको उन्हें docker rm <ContainerName>पहले का उपयोग करके निकालना होगा । एक कंटेनर निकाले जाने के बाद, आप बस इसे शुरू नहीं कर सकते docker start। इसका उपयोग करके किया जाना चाहिए docker run, जो स्वयं एक नए कंटेनर-इंस्टेंस बनाने के लिए नवीनतम छवि का उपयोग करता है।

कंटेनरों को यथासंभव स्वतंत्र होना चाहिए

इस ज्ञान के साथ, यह समझ में नहीं आता है कि कंटेनरों में डेटा संग्रहीत करना क्यों खराब अभ्यास के रूप में योग्य है और डॉकर इसके बजाय डेटा वॉल्यूम / माउंटिंग होस्ट निर्देशिकाओं की सिफारिश करता है : चूंकि अनुप्रयोगों को अपडेट करने के लिए कंटेनर को नष्ट करना पड़ता है, इसलिए अंदर संग्रहीत डेटा भी खो जाएगा। यह सेवाओं, बैकअप डेटा और इतने पर बंद करने के लिए अतिरिक्त काम का कारण बनता है।

इसलिए यह उन डेटा को कंटेनर से पूरी तरह से बाहर करने का एक स्मार्ट समाधान है: हमें अपने डेटा के बारे में चिंता करने की ज़रूरत नहीं है, जब इसके होस्ट और कंटेनर पर सुरक्षित रूप से संग्रहीत किया जाता है, केवल एप्लिकेशन ही रखता है।

-rfवास्तव में आपकी मदद क्यों नहीं कर सकते

docker runआदेश, एक है स्वच्छ ऊपर स्विच कहा जाता -rf। यह डॉक कंटेनर को स्थायी रूप से रखने के व्यवहार को रोक देगा। उपयोग -rfकरने के बाद, डोकर कंटेनर से बाहर निकल जाने के बाद उसे नष्ट कर देगा। लेकिन इस स्विच में दो समस्याएं हैं:

  1. डॉकटर कंटेनर से जुड़े नाम के बिना वॉल्यूम को भी हटा देता है, जो आपके डेटा को मार सकता है
  2. इस विकल्प का उपयोग करके, -dस्विच का उपयोग करके कंटेनरों को पृष्ठभूमि में चलाना संभव नहीं है

जबकि -rfस्विच त्वरित परीक्षणों के लिए विकास के दौरान काम को बचाने के लिए एक अच्छा विकल्प है, यह उत्पादन में कम उपयुक्त है। विशेष रूप से पृष्ठभूमि में एक कंटेनर चलाने के लिए लापता विकल्प के कारण, जो कि ज्यादातर आवश्यक होगा।

कंटेनर को कैसे निकालना है

कंटेनर को हटाकर हम उन सीमाओं को दरकिनार कर सकते हैं:

docker rm --force <ContainerName>

--force(या -fजो कंटेनर चलाने पर SIGKILL का उपयोग करें) स्विच। इसके बजाय, आप कंटेनर को पहले भी रोक सकते थे:

docker stop <ContainerName>
docker rm <ContainerName>

दोनों बराबर हैं। docker stopभी SIGTERM का उपयोग कर रहा है । लेकिन --forceस्विच का उपयोग करने से आपकी स्क्रिप्ट छोटी हो जाएगी, खासकर सीआई सर्वर का उपयोग करते समय: docker stopयदि कंटेनर नहीं चल रहा है तो एक त्रुटि फेंकता है। यह जेनकिन्स और कई अन्य सीआई सर्वरों के निर्माण को गलत तरीके से विफल मानने का कारण होगा। इसे ठीक करने के लिए, आपको पहले जांचना होगा कि कंटेनर चल रहा है जैसा कि मैंने प्रश्न में किया था ( containerRunningचर देखें )।

एक डॉकर कंटेनर के पुनर्निर्माण के लिए पूरी स्क्रिप्ट

इस नए ज्ञान के अनुसार, मैंने अपनी स्क्रिप्ट निम्नलिखित तरीके से तय की:

#!/bin/bash
imageName=xx:my-image
containerName=my-container

docker build -t $imageName -f Dockerfile  .

echo Delete old container...
docker rm -f $containerName

echo Run new container...
docker run -d -p 5000:5000 --name $containerName $imageName

यह पूरी तरह से काम करता है :)


4
'मैंने पाया कि मुझे डॉकटर कंटेनरों के जीवनकाल के बारे में कुछ गलतफहमियां थीं' आपने मेरे मुंह से सही शब्द निकाले। इस तरह की विस्तृत व्याख्या के लिए धन्यवाद। मैं यह सलाह दूंगा कि हम नया करने के लिए। यह वीएम बनाम कंटेनर के अंतर को स्पष्ट करता है।
विंस बैनज़ोन

2
आपके स्पष्टीकरण के बाद, मैंने जो कुछ किया, उस पर ध्यान दिया कि मैंने अपनी मौजूदा छवि का क्या किया। बदलावों को बनाए रखने के लिए, मैंने एक नई छवि बनाने के लिए एक नया डॉकफाइल बनाया, जिसमें पहले से ही बदलाव शामिल हैं जिन्हें मैं जोड़ना चाहता हूं। इस तरह, बनाई गई नई छवि (कुछ हद तक) अपडेट की गई है।
विंस बैनज़ॉन

क्या --force-recreateडॉकटर का विकल्प आपके द्वारा यहां वर्णित के समान है? और यदि ऐसा है, तो इसके बजाय इस समाधान का उपयोग करने के लायक नहीं होगा (खेद है कि अगर सवाल गूंगा है, लेकिन मैं एक काम कर रहा हूँ
no

2
@cglacet हां, यह समान है, सीधे तुलना करने योग्य नहीं है। लेकिन docker-composeसादे dockerआदेशों की तुलना में अधिक स्मार्ट है । मैं नियमित रूप से काम करता हूं docker-composeऔर परिवर्तन का पता लगाने में अच्छी तरह से काम करता है, इसलिए मैं उपयोग करता हूं--force-recreate बहुत कम । उदाहरण के लिए डॉकटर हब से एक छवि का उपयोग करने के बजाय docker-compose up --buildजब आप एक कस्टम छवि ( buildरचना फ़ाइल में निर्देश) का निर्माण कर रहे हैं तो बस महत्वपूर्ण है ।
सिंह

33

जब भी dockerfile या कंपोज़ या आवश्यकताओं में परिवर्तन किया जाता है, तो इसका उपयोग करके फिर से चलाएँ docker-compose up --build। ताकि छवियों का पुनर्निर्माण और ताज़ा हो जाए


1
एक सेवा के रूप में एक MySQL डॉकटर कंटेनर होने के बाद, क्या डीबी उसके बाद खाली हो जाएगा यदि कोई इसके लिए वॉल्यूम का उपयोग करता है /opt/mysql/data:/var/lib/mysql?
मार्टिन थूमा

मेरे लिए, वहाँ हमेशा --buildस्थानीय देव वातावरण में उपयोग करने के लिए किसी भी नकारात्मक नहीं लगता है। जिस गति से डॉकटर उन फाइलों को फिर से कॉपी करता है जो अन्यथा मान सकते हैं कि नकल की आवश्यकता नहीं है केवल कुछ मिलीसेकंड ले लो, और यह बड़ी संख्या में डब्ल्यूटीएफ क्षणों को बचाता है।
डैनैक

0

आप buildएक विशिष्ट सेवा के लिए दौड़ सकते हैं docker-compose up --build <service name>जहां सेवा नाम का मिलान होना चाहिए कि आपने इसे अपने डॉकटर-कम्पोज़ फ़ाइल में कैसे कॉल किया।

उदाहरण मान लें कि आपकी डॉक-कम्पोज़ फ़ाइल में कई सेवाएँ (.net ऐप - डेटाबेस - चलो एन्क्रिप्ट ... आदि) हैं और आप केवल .net ऐप को अपडेट करना चाहते हैं, जिसे applicationडॉकटर-कंपोज़ फ़ाइल में नाम दिया गया है। फिर आप बस चला सकते हैंdocker-compose up --build application

अतिरिक्त पैरामीटर यदि आप अपनी कमांड में अतिरिक्त पैरामीटर जोड़ना चाहते हैं जैसे -dकि पृष्ठभूमि में चलने के लिए, सेवा नाम से पहले पैरामीटर होना चाहिए: docker-compose up --build -d application

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.