Dockerfile में सशर्त COPY / ADD?


103

मेरे डॉकरीफ़ाइल्स के अंदर मैं अपनी छवि में एक फ़ाइल को कॉपी करना चाहूंगा यदि यह मौजूद है, तो पाइप के लिए आवश्यकताएँ.txt फ़ाइल एक अच्छे उम्मीदवार की तरह लगती है लेकिन यह कैसे प्राप्त होगी?

COPY (requirements.txt if test -e requirements.txt; fi) /destination
...
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

या

if test -e requirements.txt; then
    COPY requiements.txt /destination;
fi
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

कृपया यहाँ देखें: docs.docker.com/reference/builder
Tuan

4
@ टुआन - क्या उस लिंक पर विशेष रूप से ऐसा करने में मदद करता है?
टूलमेकरसेव

जवाबों:


24

यह वर्तमान में समर्थित नहीं है (जैसा कि मुझे संदेह है कि यह गैर-प्रतिलिपि प्रस्तुत करने योग्य छवि को जन्म देगा, क्योंकि एक ही डॉकरफाइल अपने अस्तित्व के आधार पर फ़ाइल की प्रतिलिपि बनाएगा या नहीं करेगा)।

यह अभी भी अनुरोध है, 13045 में , वाइल्डकार्ड का उपयोग करते हुए: " COPY foo/* bar/" not work if no file in foo" (मई 2015)।
इसे अभी (जुलाई 2015) के लिए डॉकर में लागू नहीं किया जाएगा, लेकिन एक अन्य बिल्ड टूल जैसे बोकर इसका समर्थन कर सकता है।


33
अच्छा जवाब है, लेकिन docker तर्क, IMO, त्रुटिपूर्ण है। यदि आप एक अलग निर्माण-संदर्भ के साथ एक ही डॉकफाइल चलाते हैं, तो आपको एक अलग छवि मिलेगी। यह उम्मीद की जानी है। उसी बिल्ड-संदर्भ का उपयोग करने से समान छवि मिलेगी। और यदि आप उसी बिल्ड-संदर्भ पर सशर्त COPY / ADD निर्देश सम्मिलित करते हैं, तो आपको एक ही छवि मिलेगी। इतना है कि बाहर की जाँच करता है। हालांकि यह सिर्फ मेरा 2 सेंट है।
nathan g

डॉकर अपरिवर्तनीय बुनियादी ढांचे के बारे में है। आपके वातावरण देवता, मंचन और ठेस समान नहीं तो संभव के रूप में 99.99% के करीब होना चाहिए। पर्यावरण चर का उपयोग करें।
एंड्रयूमैक्लागन

3
@AndrewMcLagan क्या होगा यदि, उदाहरण के लिए, एक फ्रंट-एंड devवातावरण एक वेबपैक देव सर्वर के साथ चलता है, और समतुल्य prodवातावरण एक /distस्थिर फ़ोल्डर के साथ काम करता है ? आज के अधिकांश फ्रंट-एंड सेटअपों में यही स्थिति है, और जाहिर है devऔर यहाँ भी prodऐसा नहीं हो सकता। तो उससे कैसे निपटें?
जीवन

मैं अपने नोड फ्रंट एंड को विकसित करने के लिए डॉकटर का उपयोग नहीं करता हूं। सामान्य वेबपैक लोकलहोस्ट: 3000 आदि ... हालांकि अभी भी आपके स्थानीय डॉक देव वातावरण को बूट करता है, इसलिए आपके नोड / रिएक्टर / कोणीय मोर्चे का अंत आपके सामान्य डॉकटर कंटेनर वातावरण में जो कुछ भी चल रहा है, उसके लिए संचार करता है। जैसे एपीआई, रेडिस, माईएसक्यूएल, मोंगो, इलास्टिक सर्च और कोई अन्य माइक्रो सर्विस। आप ..could .., एक कंटेनर में एक वेबपैक देव वातावरण चलाएँ। लेकिन मुझे लगता है कि यह बहुत दूर है ...
एंड्रयू मैकलेगन

@ जीवन सामान्य निर्देशों को परिभाषित करने और फिर देव और उत्पादों के लिए विशिष्ट छवियों के निर्माण के लिए एक ओनलाइन छवि का उपयोग करने के बारे में कैसे। Docker Hub Node repo में प्रत्येक Node संस्करण के लिए छवियों को बनाना शामिल है: hub.docker.com/_/node । या हो सकता है कि आप अपना रोल कर सकें।
david_i_smith

84

यहाँ एक सरल उपाय है:

COPY foo file-which-may-exist* /target

सुनिश्चित करें कि fooमौजूद है, क्योंकि COPYकम से कम एक वैध स्रोत की आवश्यकता है।

यदि file-which-may-existमौजूद है, तो इसकी प्रतिलिपि भी बनाई जाएगी।

नोट: आपको यह सुनिश्चित करने के लिए ध्यान रखना चाहिए कि आपका वाइल्डकार्ड अन्य फ़ाइलों को नहीं उठाता है जिन्हें आप कॉपी करने का इरादा नहीं रखते हैं। अधिक सावधान रहने के लिए, आप file-which-may-exist?इसके बजाय उपयोग कर सकते हैं ( ?केवल एक वर्ण से मेल खाता है)।

या इससे भी बेहतर, यह सुनिश्चित करने के लिए एक वर्ण वर्ग का उपयोग करें कि केवल एक फ़ाइल का मिलान किया जा सकता है:

COPY foo file-which-may-exis[t] /target

1
क्या आप एक फ़ोल्डर के साथ एक ही काम कर सकते हैं?
बेंजामिन तोएज

1
@BenjaminToueg: हाँ, डॉक्स के अनुसार आप फ़ाइलों के साथ-साथ फ़ोल्डरों को भी कॉपी कर सकते हैं।
jdhildeb

2
यह बहुत अच्छा काम करता है। कई गंतव्यों वाली फ़ाइलों के लिए, मैंने एक अस्थायी निर्देशिका में प्रतिलिपि बनाई और फिर उन्हें आवश्यकतानुसार स्थानांतरित कर दिया। COPY --from=docker /usr/bin/docker /usr/lib/libltdl.so* /tmp/docker/ RUN mv /tmp/docker/docker /usr/bin/docker RUN mv /tmp/docker/libltdl.so.7 /usr/lib/libltdl.so.7 || true(जहाँ साझा पुस्तकालय अज्ञात इकाई है।)
एडम के डीन

कई अतिरिक्त फ़ाइलों की प्रतिलिपि बनाते समय गंतव्य को एक निर्देशिका होना चाहिए। यह कैसे काम करता है जब दोनों foo और आपकी फ़ाइल-जो-हो सकता है * मौजूद है?
मेल्चिरो55

1
तो जवाब है 'सुनिश्चित करें कि कोई फ़ाइल है' और फिर COPY ऑपरेटर का उपयोग कैसे करें इस पर एक प्रदर्शन? मैं यह देखने में विफल हूं कि यह मूल प्रश्न से कैसे संबंधित है।
derrend

27

जैसा कि इस टिप्पणी द्वारा कहा गया है , संतोष संतोष के जवाब अभी भी फ़ाइल को कॉपी करते हैं, एक सच्ची सशर्त कॉपी को संग्रहीत करने के लिए, आप इस पद्धति का उपयोग कर सकते हैं।

ARG BUILD_ENV=copy

FROM alpine as build_copy
ONBUILD COPY file /file

FROM alpine as build_no_copy
ONBUILD RUN echo "I don't copy"

FROM build_${BUILD_ENV}
# other stuff

ONBUILDनिर्देश सुनिश्चित करता है कि फ़ाइल केवल नकल की जाती है, तो "शाखा" से चुना जाता है BUILD_ENV। कॉल करने से पहले थोड़ी स्क्रिप्ट का उपयोग करके इस संस्करण को सेट करेंdocker build


2
मुझे यह उत्तर पसंद है क्योंकि इसने मेरी आँखें न केवल ONBUILD के लिए खोलीं, जो सुपर हैण्ड है, बल्कि इसमें पारित अन्य वैरिएबल्स के साथ एकीकृत करना भी सबसे आसान लगता है, जैसे यदि आप BUILD_ENV पर आधारित टैग सेट करना चाहते हैं, या किसी राज्य को स्टोर करना चाहते हैं ENV।
DeusXMachina

मैंने ऐसा कुछ करने की कोशिश की और मिला: डेमॉन से त्रुटि प्रतिक्रिया: डॉकरीफाइल पार्स एरर लाइन 52: बिल्ड स्टेज के लिए अमान्य नाम: "साइट_बिल्डर _ $ {host_env}", नाम एक नंबर से शुरू नहीं हो सकता है या इसमें प्रतीक नहीं हैं
paulecoyote

9

समाधान के आसपास काम करें

मुझे ईएनवी वेरिएबल्स पर आधारित सर्वर को कॉपी फॉल्डर की आवश्यकता थी। मैंने खाली सर्वर छवि ली। स्थानीय फ़ोल्डर में आवश्यक परिनियोजन फ़ोल्डर संरचना बनाया। फिर DockerFile के नीचे लाइन को कंटेनर में कॉपी करें। मैं सर्वर शुरू करने से पहले init file.sh को निष्पादित करने के लिए अंतिम पंक्ति जोड़ा प्रविष्टि बिंदु n।

#below lines added to integrate testing framework
RUN mkdir /mnt/conf_folder
ADD install /mnt/conf_folder/install
ADD install_test /mnt/conf_folder/install_test
ADD custom-init.sh /usr/local/bin/custom-init.sh
ENTRYPOINT ["/usr/local/bin/custom-init.sh"]

फिर स्थानीय- script.sh फ़ाइल को स्क्रिप्ट के साथ बनाएँ जैसे नीचे कुछ

#!/bin/bash
if [ "${BUILD_EVN}" = "TEST" ]; then
    cp -avr /mnt/conf_folder/install_test/* /mnt/wso2das-3.1.0/
else
    cp -avr /mnt/conf_folder/install/* /mnt/wso2das-3.1.0/
fi;

में डोकर-लिखें लाइनों नीचे फ़ाइल।

पर्यावरण: - BUILD_EVN = परीक्षण

डॉक बिल्ड के दौरान ये परिवर्तन फ़ोल्डर को कॉपी करते हैं। जब हम docker-compose को निष्पादित करते हैं तो सर्वर शुरू होने से पहले सर्वर पर वास्तविक आवश्यक फ़ोल्डर को कॉपी या तैनात कर देते हैं।


8
लेकिन डॉकटर इमेज स्तरित हैं। ADD छवि की परवाह किए बिना यदि आपने उल्लेख किया है तो इनकी नकल करेगा ...
MyUserInStackOverflow

@MyUserInStackOverflow - मुझे लगता है कि इस "वर्कअराउंड" का विचार यह है कि इंस्टॉल और इंस्टॉल_ दोनों को छवि में कॉपी किया जाता है, लेकिन जब छवि चलती है, तो केवल उन फ़ोल्डरों में से एक को अंतिम स्थान पर कॉपी किया जाता है। अगर यह ठीक है कि दोनों छवि में कहीं हैं, तो यह एक उचित तकनीक हो सकती है।
टूलमेकरसेव

5

सभी फ़ाइलों को एक फेंकने की डायर पर कॉपी करें, जो आप चाहते हैं, उसे चुनें, बाकी को छोड़ दें।

COPY . /throwaway
RUN cp /throwaway/requirements.txt . || echo 'requirements.txt does not exist'
RUN rm -rf /throwaway

आप बिल्ड चरणों का उपयोग करके कुछ समान हासिल कर सकते हैं, जो cpसशर्त रूप से कॉपी का उपयोग करके उसी समाधान पर निर्भर करता है। बिल्ड स्टेज का उपयोग करके, आपकी अंतिम छवि में प्रारंभिक से सभी सामग्री शामिल नहीं होगी COPY

FROM alpine as copy_stage
COPY . .
RUN mkdir /dir_for_maybe_requirements_file
RUN cp requirements.txt /dir_for_maybe_requirements_file &>- || true

FROM alpine
# Must copy a file which exists, so copy a directory with maybe one file
COPY --from=copy_stage /dir_for_maybe_requirements_file /
RUN cp /dir_for_maybe_requirements_file/* . &>- || true
CMD sh

जबकि यह तकनीकी रूप से समस्या को हल करता है, यह छवि के आकार को कम नहीं करता है। यदि आप सशर्त रूप से कुछ विशाल (एक गहरे नेटवर्क मॉडल की तरह) कॉपी करने की कोशिश कर रहे हैं, तो आप ओवरले एफएस के काम करने के तरीके के कारण अभी भी छवि का आकार बढ़ाते हैं।
डेसएक्समैचिना

@DeusXMachina, आप किस संस्करण का उपयोग कर रहे हैं? डॉक्स विरोधाभास करते हैं कि आप क्या कह रहे हैं docs.docker.com/develop/develop-images/multistage-build/… । परतों को एक गैर-अंतिम बिल्ड स्टेज से संरक्षित नहीं किया जाना चाहिए।
cdosborn

@ LCDosburn - मैंने 18.09 को इसे देखा है। मैं ज्यादातर पहले उदाहरण के बारे में बोल रहा था, मंचित बिल्ड को उस मुद्दे से बचना चाहिए। और मुझे लगता है कि हर मंच से अब कॉम्पैक्ट हो जाता है, लेकिन आप मुझे मेरे स्मरण का अनुमान लगाते हैं। मुझे कुछ चीजों के साथ प्रयोग करना पड़ेगा।
DeusXMachina

@DeusXMachina, सही केवल दूसरा समाधान छवि का आकार कम करता है।
cdosborn

यह मेरे मामले के लिए अच्छा समाधान है। मैं एक कॉपी cacheकरता हूं और व्हाट्सएप पर निर्भर करता है कि मैं स्क्रिप्ट फाइलों में क्या चुनूं!
पसलीस

1

अन्य विचारों की कोशिश की, लेकिन हमारी आवश्यकता को पूरा नहीं किया। यह विचार बाल स्थैतिक वेब अनुप्रयोगों के लिए बेस नगनेक्स इमेज बनाने का है। सुरक्षा, अनुकूलन और मानकीकरण कारणों के लिए, आधार छवि को RUNबाल चित्रों द्वारा जोड़ी गई निर्देशिकाओं पर कमांड करने में सक्षम होना चाहिए । आधार छवि नियंत्रित नहीं करती है कि कौन सी निर्देशिकाओं को बाल छवियों द्वारा जोड़ा जाता है। मान लिया गया है कि बाल चित्र COPYकहीं संसाधनों के तहत होंगे COMMON_DEST_ROOT

यह दृष्टिकोण एक हैक है, लेकिन विचार आधार छवि है COPYजो बाल छवि द्वारा जोड़े गए 1 से एन निर्देशिकाओं के लिए निर्देश का समर्थन करेगा । ARG PLACEHOLDER_FILEऔर किसी भी अनुदेश की आवश्यकता के लिए ENV UNPROVIDED_DESTसंतुष्ट करने <src>और <dest>आवश्यकताओं के लिए उपयोग किया जाता है COPY

#
# base-image:01
#
FROM nginx:1.17.3-alpine
ENV UNPROVIDED_DEST=/unprovided
ENV COMMON_DEST_ROOT=/usr/share/nginx/html
ONBUILD ARG PLACEHOLDER_FILE
ONBUILD ARG SRC_1
ONBUILD ARG DEST_1
ONBUILD ARG SRC_2
ONBUILD ARG DEST_2
ONBUILD ENV SRC_1=${SRC_1:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_1=${DEST_1:-${UNPROVIDED_DEST}}
ONBUILD ENV SRC_2=${SRC_2:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_2=${DEST_2:-${UNPROVIDED_DEST}}

ONBUILD COPY ${SRC_1} ${DEST_1}
ONBUILD COPY ${SRC_2} ${DEST_2}

ONBUILD RUN sh -x \
    #
    # perform operations on COMMON_DEST_ROOT
    #
    && chown -R limited:limited ${COMMON_DEST_ROOT} \
    #
    # remove the unprovided dest
    #
    && rm -rf ${UNPROVIDED_DEST}

#
# child image
#
ARG PLACEHOLDER_FILE=dummy_placeholder.txt
ARG SRC_1=app/html
ARG DEST_1=/usr/share/nginx/html/myapp
FROM base-image:01

इस समाधान में डमी PLACEHOLDER_FILEऔर हार्ड-कोडित संख्या जैसे COPY निर्देशों की स्पष्ट कमियां हैं जो समर्थित हैं। इसके अलावा सीओपीवाई अनुदेश में उपयोग किए जाने वाले ईएनवी चर से छुटकारा पाने का कोई तरीका नहीं है।

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