Docker Compose में multiple files का उपयोग कैसे करें
Docker Compose में compose.override.yaml के ऑटो-लोडिंग व्यवहार, फाइलों के मर्जिंग क्रम और ports कॉन्फ़िगरेशन की समस्याओं को समझें। dev और prod वातावरण के लिए include का सही उपयोग सीखें।
Compose एक से अधिक फाइलों के साथ क्या करता है
Docker Compose एक ही प्रोजेक्ट को कई फाइलों से बना सकता है। यह उन्हें उसी क्रम में पढ़ता है जिस क्रम में वे प्राप्त होती हैं और उन्हें एक एकल मॉडल में मर्ज कर देता है, इसलिए किसी भी conflicting मान पर बाद वाली फाइल प्रभावी होती है। कमांड लाइन से ऐसा करने के दो तरीके हैं: एक override फाइल जिसे Compose स्वयं लोड करता है, और -f फ्लैग जिसे आप मैन्युअल रूप से पास करते हैं। तीसरा तरीका फाइल के भीतर ही मौजूद होता है, जो include एलिमेंट है, और यह दोनों से अलग तरह से काम करता है।
यह मर्ज केवल साधारण overwrite नहीं है। Mappings को key-by-key मर्ज किया जाता है, sequences को append किया जाता है, और कुछ चुनिंदा fields को पूरी तरह से बदल दिया जाता है। यही अंतर आश्चर्य का कारण बनता है, और ports सूची वह है जो लगभग हर किसी को उलझा देती है।
नीचे दी गई सभी जानकारी Compose v2, यानी पुराने docker-compose स्क्रिप्ट के बजाय docker compose प्लगइन को मानकर दी गई है। जाँचने के लिए docker compose version चलाएँ। यदि आपने अभी तक कोई Compose फाइल नहीं लिखी है, तो Docker Compose बेसिक्स गाइड से शुरुआत करें और फिर वापस आएँ।
वह override file जिसे Compose बिना बताए लोड करता है
यदि आप docker compose up को बिना किसी -f flag के चलाते हैं, तो Compose वर्तमान directory और उसके parent directories में compose.yaml या docker-compose.yaml को खोजता है। यदि base file के साथ कोई override file मौजूद होती है, तो Compose उसे अपने आप दूसरे नंबर पर लोड कर लेता है।
ls compose.yaml compose.override.yaml
docker compose up -dदोनों फाइलें मौजूद होने पर, यह वैसा ही है जैसे उन्हें मैन्युअल रूप से टाइप किया गया हो।
docker compose -f compose.yaml -f compose.override.yaml up -dCompose जिन नामों को पहचानता है वे हैं compose.override.yaml, compose.override.yml, और पुराने docker-compose.override.yml तथा docker-compose.override.yaml। कोई अन्य नाम, जैसे कि compose.dev.yaml, केवल तभी लोड होता है जब आप उसे -f के साथ निर्दिष्ट करते हैं।
जैसे ही आप एक -f पास करते हैं, automatic loading बंद हो जाती है। docker compose -f compose.yaml up केवल उसी एक फाइल को पढ़ता है और override को अनदेखा कर देता है। इसी विशेषता पर इस गाइड में बाद में बताया गया dev और prod पैटर्न आधारित है।
सर्वर पर इसका असर दोनों दिशाओं में हो सकता है। deploy directory में रखी गई override file उस directory से चलने वाले हर bare docker compose command द्वारा load होती है, जिसमें आपका cron job चलाने वाला command भी शामिल है। इसी कारण production stack ऐसी source directory को bind-mount कर सकता है जिसे deploy करने का किसी का इरादा नहीं था। हर deploy के बाद docker compose config चलाएँ और उसका output पढ़ें। जब deploy unattended हो, तो यह जाँच तभी उपयोगी है जब कोई आपको failure की सूचना दे। यही काम self-hosted ntfy server जैसे push channel का है, जिस पर cron job या systemd OnFailure unit notification भेज सकती है।
-f के साथ क्रम निर्धारण, और रिलेटिव पाथ कहाँ रिजॉल्व होते हैं
Compose आपके द्वारा दी गई फाइलों के क्रम में कॉन्फ़िगरेशन बनाता है, और बाद वाली फाइलें पिछली फाइलों को ओवरराइड करती हैं और उनमें जुड़ती हैं। बाएं से दाएं, अंतिम फाइल प्रभावी होती है।
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -dउस project में हर command के लिए वही file list होनी चाहिए। दो files के साथ up और एक file के साथ logs चलाने पर आप किसी अलग merged model के साथ काम कर रहे होते हैं। इससे ऐसी service बन सकती है जिसे Compose मौजूद नहीं मानता। यह जोखिम उस stack में और बढ़ जाता है जिसमें upgrades one-off commands से चलते हैं, जैसे self-hosted Chatwoot support desk में database migration step। वहाँ गलत file list के साथ जारी किया गया docker compose run चुपचाप उस model को target करता है जो आपकी services पहले से उपयोग कर रही model से अलग है। इसके बजाय COMPOSE_FILE environment variable से list को एक बार निर्धारित करें।
export COMPOSE_FILE=compose.yaml:compose.prod.yaml
docker compose config
docker compose up -dLinux पर सेपरेटर : है, और COMPOSE_PATH_SEPARATOR इसे बदल देता है। COMPOSE_FILE को प्रोजेक्ट की .env फाइल में भी रखा जा सकता है, जिससे यह आपके शेल हिस्ट्री के बजाय चेकआउट का हिस्सा बन जाता है। कमांड लाइन पर स्पष्ट रूप से सेट की गई कोई भी चीज़ एनवायरनमेंट वेरिएबल से अधिक प्रभावी होती है।
अब वह नियम जो बाइंड माउंट्स (bind mounts) को प्रभावित करता है। जब आप -f के साथ कई फाइलों का उपयोग करते हैं, तो उन सभी फाइलों में मौजूद सभी रिलेटिव पाथ पहली फाइल की डायरेक्टरी के सापेक्ष रिजॉल्व होते हैं, न कि उस फाइल के सापेक्ष जिसमें वे लिखे गए हैं। यदि आप deploy/prod/compose.prod.yaml के अंदर ./data:/var/lib/postgresql/data लिखते हैं, तो भी Compose ./data को बेस फाइल के बगल में ही खोजेगा। Docker तब उस गलत पाथ पर एक खाली डायरेक्टरी बना देता है और कंटेनर बिना किसी डेटा के स्टार्ट होता है, जो डेटा लॉस जैसा दिखता है, लेकिन ऐसा होता नहीं है। बेस पाथ को स्वयं सेट करने के लिए --project-directory पास करें, या include का उपयोग करें, जो प्रत्येक फाइल को उसकी अपनी डायरेक्टरी के सापेक्ष रिजॉल्व करता है।
प्रोजेक्ट का नाम उसी बेस डायरेक्टरी से आता है, इसलिए पहली फाइल को बदलने से प्रोजेक्ट का नाम बदल सकता है। प्रोजेक्ट का नाम बदलने का मतलब है नए कंटेनर नाम और नए वॉल्यूम नाम, और पुराना वॉल्यूम अभी भी पुराने नाम के तहत डिस्क पर मौजूद रहता है। इसके बजाय, बेस फाइल में टॉप-लेवल name: के साथ इसे पिन करें।
name: myappकौन से fields मर्ज होते हैं और कौन से replace किए जाते हैं
Compose fields को उनके नाम से नहीं, बल्कि value के प्रकार के आधार पर मर्ज करता है।
- Single-valued fields को replace किया जाता है।
image,command,entrypointऔरmem_limitबाद वाली value को पूरी तरह से अपना लेते हैं। आप किसीcommandमें एक argument को append नहीं कर सकते, क्योंकि override पूरी लाइन को फिर से लिख देता है। - Mappings को key-by-key मर्ज किया जाता है।
environment,labels,volumesऔरdevicesदोनों फाइलों की सभी keys को बनाए रखते हैं, और दोनों में मौजूद किसी भी key के लिए बाद वाली फाइल की value प्रभावी होती है।environmentऔरlabelsके लिए key, variable या label का नाम होती है।volumesऔरdevicesके लिए key, container का path होती है। - Sequences को append किया जाता है।
dns,dns_search,expose,tmpfsऔरexternal_linksको आपस में जोड़ दिया जाता है। एक base जिसमेंexpose: ["3000"]है, उसे एक override के साथ मर्ज करने पर जिसमें["4000", "5000"]है, परिणाम["3000", "4000", "5000"]मिलता है।
चार sequences में एक identity key होती है, इसलिए उस key पर मेल खाने वाली entries append होने के बजाय मर्ज हो जाती हैं। volumes, secrets और configs, target पर मेल खाती हैं। ports, ip, target, published और protocol के संयोजन पर मेल खाती है।
उस ports नियम को दो बार पढ़ें, क्योंकि यही वह जगह है जहाँ गलती हो सकती है। दो port entries केवल तभी एक ही entry मानी जाती हैं जब वे चारों भाग आपस में मेल खाते हों। उनमें से किसी एक को भी बदलने पर Compose उसे एक दूसरी, असंबंधित port के रूप में देखता है, इसलिए वह दोनों को बनाए रखता है।
आपका port override के बाद भी published क्यों रहता है
एक base file जो हर interface पर service को publish करती है:
services:
web:
image: nginx:1.27
ports:
- "8080:80"एक override जिसे केवल localhost पर bind करने के लिए लिखा गया है, क्योंकि इसके सामने एक reverse proxy होगा:
services:
web:
ports:
- "127.0.0.1:8080:80"यह मानने से पहले कि यह काम कर गया, परिणाम की जाँच करें।
docker compose -f compose.yaml -f compose.prod.yaml configदोनों entries output में मौजूद हैं। ip भाग अलग है, 0.0.0.0 बनाम 127.0.0.1, इसलिए merge के संदर्भ में ये दो अलग ports हैं, और public binding जिसे आप हटाना चाहते थे, वह अभी भी model में है। यह Docker पर अन्य जगहों की तुलना में अधिक मायने रखता है, क्योंकि एक published port आपके firewall rules से पहले iptables में लिख दिया जाता है। यह mechanism why published Docker ports walk past ufw में कवर किया गया है।
इसके दो समाधान हैं। स्पष्ट समाधान !override tag है, जो पूरे attribute को replace कर देता है और merge rules को छोड़ देता है:
services:
web:
ports: !override
- "127.0.0.1:8080:80"!override के लिए Compose v2.24.4 या उससे नया version चाहिए। portable समाधान के लिए किसी tag की आवश्यकता नहीं है: ports को base file से पूरी तरह बाहर रखें और इसे केवल environment-specific files में ही declare करें। जब merge करने के लिए कुछ नहीं होगा, तो कुछ भी leak नहीं होगा। नीचे दिए गए worked example में इसी pattern का उपयोग किया गया है।
बेस फाइल सेट से किसी वैल्यू को हटाना
!reset एक attribute को हटा देता है, जिससे वह अपने default मान पर या null पर वापस आ जाता है। यह एक value लेता है और उसे अनदेखा कर देता है, इसलिए कोई वैध और खाली मान लिखें।
services:
web:
ports: !reset []
environment:
DEBUG: !reset null!reset के लिए Compose v2.24 या उससे नया वर्ज़न आवश्यक है। इसका उपयोग तब करें जब base file को edit करना आपके अधिकार में न हो, उदाहरण के लिए, किसी vendor fragment के लिए जिसे आप pull करते हैं। एक published upstream stack बिल्कुल ऐसा ही मामला है: एक self-hosted AFFiNE workspace के पीछे की Compose file चार ऐसे containers घोषित करती है जिन्हें आपने नहीं लिखा है, और !reset आपको फाइल को fork किए बिना और उसे ट्रैक करने की जिम्मेदारी लिए बिना उनमें से किसी एक पर एक attribute को clear करने की सुविधा देता है।
include, उन stacks के लिए जो अलग-अलग हिस्सों से बने हैं
include आपके मॉडल में एक और Compose application को शामिल करता है। यह एक top-level element है, न कि कोई flag।
include:
- path: ../commons/compose.yamlinclude में प्रत्येक path को उसके अपने Compose application मॉडल के रूप में लोड किया जाता है, जिसका अपना project directory होता है। इसलिए उस file के भीतर के relative paths उसी file की directory के सापेक्ष resolve होते हैं। यही -f से इसका वास्तविक अंतर है, और यही कारण है कि जब कोई fragment किसी अन्य folder या repository में स्थित हो, तो include सही tool है। यह किसी ऐसे vendor stack का सामान्य स्वरूप है जिसे आपने नहीं लिखा है: एक self-hosted Authentik SSO install के पीछे की multi-service Compose file अपनी directory में अपने relative paths के साथ सुरक्षित रह सकती है, जबकि आपकी file केवल आपकी अपनी services तक सीमित रहती है।
इसका long form sub-options भी स्वीकार करता है।
include:
- path:
- ../monitoring/compose.yaml
- ../monitoring/compose.vps.yaml
project_directory: ../monitoring
env_file: ../monitoring/.envpath एक list स्वीकार करता है, और उन files को सामान्य नियमों के साथ merge किया जाता है, जिसके बाद परिणाम आपके मॉडल में जुड़ जाता है। project_directory उस base path को set करता है जिसका उपयोग शामिल की गई file में relative paths को resolve करने के लिए किया जाता है। env_file शामिल की गई file को interpolation के लिए अपने स्वयं के variables देता है, जो एक shared fragment को चुपचाप आपके project की .env को पढ़ने से रोकता है। include के लिए Compose v2.20.0 या उससे नया version आवश्यक है। यही options उस stack के लिए भी उपयुक्त हैं जिसे आप पहले से चला रहे हैं, उदाहरण के लिए Halcyon, जो Jellyfin library को 90 के दशक के रेंटल स्टोर जैसा रूप देता है: इसकी file अपना image tag और अपना env_file रखती है, इसलिए इसे upgrade करने का मतलब कभी भी उस file को बदलना नहीं होता जिसमें आपका media stack स्थित है।
आपकी file और शामिल की गई file के बीच duplicate resource names होने पर उन्हें चुपचाप merge करने के बजाय error के रूप में report किया जाता है, और यह जानबूझकर किया गया है। शामिल की गई file द्वारा घोषित किसी चीज़ को बदलने के लिए, उस बदलाव को compose.override.yaml में रखें: override को assembled मॉडल पर लागू किया जाता है, इसलिए यह शामिल किए गए resources को उनके साथ टकराए बिना बदल सकता है। यह आदत उस stack के साथ सबसे अधिक फायदेमंद होती है जिसकी upstream file हर release पर फिर से लिखी जाती है, जैसे कि PhotoPrism बनाम Immich में तुलना किए गए multi-container photo servers, जहाँ localhost binding या अतिरिक्त volume को आपकी override file में होना चाहिए, न कि उस file में जिसे अगला upgrade बदल देगा।
संक्षेप में: include अलग-अलग applications को जोड़ता है, -f एक ही application पर configuration की परतें चढ़ाता है।
एक VPS पर dev और prod का विभाजन
यहाँ पूरा पैटर्न तीन फाइलों में दिया गया है। बेस फाइल यह घोषित करती है कि हर जगह क्या लागू होगा, और यह कोई भी पोर्ट पब्लिश नहीं करती है।
name: myapp
services:
app:
image: ghcr.io/example/app:1.4.2
environment:
DATABASE_URL: postgres://app:${POSTGRES_PASSWORD}@db:5432/app
LOG_LEVEL: info
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_DB: app
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
db_data:depends_on कंडीशन वह है जो ऐप को ऐसे डेटाबेस के लिए प्रतीक्षा करने पर मजबूर करती है जो वास्तव में रिस्पॉन्स दे रहा हो, न कि केवल ऐसे कंटेनर के लिए जो अस्तित्व में है। इसकी व्याख्या healthchecks और depends_on कंडीशंस में की गई है। POSTGRES_PASSWORD को प्रोजेक्ट की .env फाइल से इंटरपोलेट किया जाता है, जिसे कभी भी git में नहीं डालना चाहिए। सुरक्षित विकल्पों के लिए env फाइल्स और Compose सीक्रेट्स देखें।
अगली फाइल compose.override.yaml है, जिसे Compose अपने आप लोड कर लेता है। यह डेवलपर की फाइल है।
services:
app:
build: .
command: npm run dev
environment:
LOG_LEVEL: debug
ports:
- "3000:3000"
volumes:
- ./src:/app/src
db:
ports:
- "127.0.0.1:5432:5432"लैपटॉप पर, एक साधारण docker compose up इन दोनों फाइलों को मर्ज कर देता है। command इमेज के डिफॉल्ट को बदल देता है क्योंकि यह सिंगल-वैल्यूड है। LOG_LEVEL, info की जगह ले लेता है क्योंकि environment की-आधारित मर्जिंग करता है। बाइंड माउंट और दो पब्लिश किए गए पोर्ट पूरी तरह से अतिरिक्त हैं, और डेटाबेस पोर्ट को localhost पर बाइंड किया गया है ताकि साझा नेटवर्क पर मौजूद लैपटॉप कमरे में किसी और को PostgreSQL उपलब्ध न कराए।
अंत में, compose.prod.yaml। इसका नाम ऐसा नहीं है जिसे Compose खुद खोजे, इसलिए यह गलती से कभी लोड नहीं होती है।
services:
app:
ports:
- "127.0.0.1:8000:3000"
deploy:
resources:
limits:
memory: 512MVPS पर आप दोनों फाइलों का नाम निर्दिष्ट करते हैं, और नाम देने की यह क्रिया ही ओवरराइड फाइल को बाहर रखती है।
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose -f compose.yaml -f compose.prod.yaml psps में दोनों सर्विसेज रनिंग दिखनी चाहिए, और db में (healthy) दिखाई देना चाहिए। चूंकि आपने -f पास किया था, इसलिए compose.override.yaml को नहीं पढ़ा गया। इस कारण dev कमांड, सोर्स बाइंड माउंट और पब्लिक पोर्ट 3000 प्रोडक्शन तक नहीं पहुँच सकते, भले ही फाइल उसी डायरेक्टरी में मौजूद हो। पोर्ट 8000 केवल localhost पर है और प्रॉक्सी के लिए तैयार है: जब आप दूसरी सर्विस जोड़ें तो Traefik के पीछे कई ऐप्स चलाना देखें।
सर्वर की .env में COMPOSE_FILE=compose.yaml:compose.prod.yaml सेट करें और आपके बाकी कमांड्स वापस साधारण docker compose logs -f app हो जाएंगे।
एक सिंगल-सर्विस स्टैक भी इसी तरह का आकार लेता है, क्योंकि एक सेल्फ-होस्टेड openGym वर्कआउट ट्रैकर को पहला पासकी एनरोल करने से पहले प्रॉक्सी के पीछे TLS पर रिस्पॉन्स देना होता है। एक बेस फाइल जिसमें कोई ports न हो, वही वह चीज है जो किसी अनचाहे पब्लिक बाइंडिंग को प्रॉक्सी से पहले काम शुरू करने से रोकती है।
डिप्लॉय करने से पहले merged model को पढ़ें
docker compose config पूरी तरह से merged और interpolated model को प्रिंट करता है। यह कोई preview नहीं है। यह वह सटीक input है जिस पर Compose कार्य करेगा, इसलिए जब output आपकी अपेक्षाओं से मेल न खाए, तो output ही सही है।
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml config --no-interpolate
docker compose -f compose.yaml -f compose.prod.yaml config --services--no-interpolate, ${VAR} को unexpanded छोड़ देता है। इसे कहीं भी output paste करने से पहले उपयोग करें, क्योंकि साधारण config हर resolved secret को clear text में प्रिंट करता है। --services केवल service के नाम सूचीबद्ध करता है, जो यह पुष्टि करने का एक त्वरित तरीका है कि include ने वही pull किया है जिसकी आपको अपेक्षा थी।
विफलता के प्रकार और आप क्या देखेंगे
no configuration file provided: not found. Compose को पढ़ने के लिए कुछ नहीं मिला। आप प्रोजेक्ट डायरेक्टरी से बाहर हैं, या COMPOSE_FILE एक ऐसे पाथ का नाम है जो मौजूद नहीं है। Compose डिफ़ॉल्ट बेस फ़ाइल के लिए पैरेंट डायरेक्टरीज़ में खोज करता है, लेकिन आपके द्वारा स्वयं नामित फ़ाइल के लिए यह कहीं भी खोज नहीं करता है।
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string. इंटरपोलेशन प्रोजेक्ट की .env फ़ाइल और शेल एनवायरनमेंट के आधार पर रिज़ॉल्व होता है, और यहाँ प्रोजेक्ट डायरेक्टरी वह डायरेक्टरी है जहाँ पहली -f फ़ाइल स्थित है। .env वाली डायरेक्टरी से अलग किसी अन्य डायरेक्टरी से डिप्लॉय करने पर आपको यह चेतावनी मिलती है और उसके बाद एक ऐसा डेटाबेस मिलता है जो हर कनेक्शन को अस्वीकार कर देता है।
आपका ओवरराइड एडिट docker compose config में दिखाई नहीं दे रहा है। या तो आपने -f पास किया है, जो ऑटोमैटिक ओवरराइड लोडिंग को बंद कर देता है, या Compose को पैरेंट डायरेक्टरी में compose.yaml मिल गया है और आपकी ओवरराइड फ़ाइल उसके बगल में नहीं है। बिना किसी अन्य तर्क के docker compose config चलाने पर आपको पता चल जाएगा कि Compose वास्तव में कौन सा मॉडल बना रहा है।
एक बाइंड माउंट खाली है और Docker ने एक ऐसी डायरेक्टरी बना दी है जिसे आपने नहीं मांगा था। रिलेटिव पाथ पहली फ़ाइल की डायरेक्टरी के आधार पर रिज़ॉल्व हुआ। पाथ को ठीक करें, --project-directory पास करें, या फ्रैगमेंट को include के पीछे ले जाएं।
कंटेनर नए नामों के साथ वापस आते हैं और एक वॉल्यूम खाली दिखता है। प्रोजेक्ट का नाम बदल गया है, क्योंकि प्रोजेक्ट का नाम पहली फ़ाइल की डायरेक्टरी का अनुसरण करता है। बेस फ़ाइल में एक टॉप-लेवल name: जोड़ें और नाम बदलना बंद हो जाएगा। पुराना वॉल्यूम अभी भी पुराने प्रीफ़िक्स के तहत मौजूद है, और docker volume ls इसे दिखाएगा।
ओवरराइड में आपके द्वारा हटाया गया पोर्ट अभी भी खुला है। ports मर्ज ने बदलने के बजाय उसे जोड़ दिया (append कर दिया)। docker compose config के साथ पुष्टि करें, फिर या तो !override का उपयोग करें या ports को बेस फ़ाइल से बाहर ले जाएं।
FAQ
क्या Compose अपने आप compose.override.yaml लोड करता है?
हाँ, जब आप बिना किसी -f फ्लैग के docker compose चलाते हैं। Compose वर्किंग डायरेक्टरी और उसके पैरेंट फोल्डर्स में compose.yaml या docker-compose.yaml को खोजता है, और यदि उसके बगल में कोई ओवरराइड फाइल मौजूद हो, तो वह फाइल दूसरी बार लोड की जाती है। पहचाने जाने वाले नाम compose.override.yaml, compose.override.yml, docker-compose.override.yml और docker-compose.override.yaml हैं। कोई भी -f पास करने से यह सुविधा बंद हो जाती है, इसलिए docker compose -f compose.yaml up केवल एक ही फाइल पढ़ता है।
कई -f फाइलों को मर्ज करने का क्रम क्या है?
बाएं से दाएं। Compose आपके द्वारा दी गई फाइलों के क्रम में कॉन्फ़िगरेशन बनाता है, और प्रत्येक फाइल अपने से पहले वाली फाइलों को ओवरराइड करती है और उनमें जोड़ती है, इसलिए लाइन में मौजूद अंतिम फाइल किसी भी संघर्ष (conflict) की स्थिति में प्रभावी रहती है। उस प्रोजेक्ट के हर कमांड के लिए एक ही सूची का उपयोग किया जाना चाहिए, जिसके लिए COMPOSE_FILE=compose.yaml:compose.prod.yaml का उपयोग होता है।
ओवरराइड करने के बाद भी मेरा पोर्ट पब्लिश क्यों है?
क्योंकि ports प्रविष्टियों की पहचान ip, target, published और protocol के पूरे सेट द्वारा की जाती है। बेस 8080:80 के मुकाबले 127.0.0.1:8080:80 का ओवरराइड ip भाग में भिन्न है, इसलिए Compose इसे दूसरे पोर्ट के रूप में मानता है और दोनों को बनाए रखता है। docker compose config चलाएं और आप दोनों प्रविष्टियां देख पाएंगे। Compose v2.24.4 या नए वर्ज़न पर ports: !override का उपयोग करें, या बेस फाइल से ports को हटा दें ताकि मर्ज करने के लिए कुछ भी न बचे।
include और -f में क्या अंतर है?
-f एक ही एप्लिकेशन पर कई फाइलों की परतें चढ़ाता है, और हर फाइल में मौजूद रिलेटिव पाथ पहली फाइल की डायरेक्टरी के आधार पर हल होते हैं। include एक अलग Compose एप्लिकेशन को शामिल करता है, और प्रत्येक शामिल पाथ अपनी प्रोजेक्ट डायरेक्टरी को बनाए रखता है, इसलिए इसके रिलेटिव पाथ खुद के आधार पर हल होते हैं। अपने स्टैक की एनवायरनमेंट लेयर्स के लिए -f का उपयोग करें, और कहीं और मेंटेन किए गए फ्रैगमेंट के लिए include का उपयोग करें। include के लिए Compose v2.20.0 या उससे नया वर्ज़न आवश्यक है।
मैं बेस फाइल द्वारा सेट की गई वैल्यू को कैसे हटाऊं?
Compose v2.24 या उससे नए वर्ज़न पर !reset टैग का उपयोग करें। ओवरराइडिंग फाइल में ports: !reset [] या MY_VAR: !reset null लिखें और एट्रिब्यूट अपने डिफ़ॉल्ट मान या null पर वापस चला जाएगा। टैग को दी जाने वाली वैल्यू आवश्यक है लेकिन उसे अनदेखा कर दिया जाता है। यदि आप किसी एट्रिब्यूट को क्लियर करने के बजाय बदलना चाहते हैं, तो !override ऐसा करता है, और इसके लिए v2.24.4 या उससे नया वर्ज़न आवश्यक है।