SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-08-29

Docker Compose میں متعدد فائلیں کیسے merge ہوتی ہیں؟

جانیں compose.override.yaml کب خود load ہوتی ہے، فائلوں کی ترتیب merge کو کیسے بدلتی ہے، ports list کے باعث پورٹ کیوں کھلا رہتا ہے، اور dev/prod split کے لیے include کب استعمال کریں۔

ایک سے زیادہ فائلوں کے ساتھ Compose کیا کرتا ہے

Docker Compose متعدد فائلوں سے ایک project بنا سکتا ہے۔ یہ فائلوں کو موصول ہونے والی ترتیب میں پڑھتا ہے اور انہیں ایک واحد model میں merge کرتا ہے، اس لیے جو value متصادم ہو اس میں بعد والی فائل غالب آتی ہے۔ کمانڈ لائن سے یہ کام کرنے کے دو طریقے ہیں: ایک override فائل جسے Compose خود load کرتا ہے، اور -f flag جسے آپ خود فراہم کرتے ہیں۔ تیسرا طریقہ خود فائل کے اندر موجود include element ہے، اور یہ دونوں سے مختلف انداز میں کام کرتا ہے۔

Merge کا مطلب سادہ overwrite نہیں ہے۔ Mappings key کے لحاظ سے merge ہوتی ہیں، sequences آخر میں شامل ہوتی ہیں، اور چند مخصوص fields مکمل طور پر replace ہوتی ہیں۔ حیرت انگیز نتائج اسی فرق کی وجہ سے آتے ہیں، اور ports list وہ فہرست ہے جس میں تقریباً ہر شخص الجھتا ہے۔

ذیل کی تمام معلومات Compose v2، یعنی پرانے docker-compose script کے بجائے docker compose plugin، کو فرض کرتی ہیں۔ جانچنے کے لیے docker compose version چلائیں۔ اگر آپ نے ابھی تک Compose فائل نہیں لکھی تو Docker Compose کے بنیادی رہنما سے شروع کریں اور پھر یہاں واپس آئیں۔

وہ override فائل جسے Compose بتائے بغیر load کرتا ہے

docker compose up کو -f flag کے بغیر چلانے پر Compose working directory اور پھر اس کی parent directories میں compose.yaml یا docker-compose.yaml تلاش کرتا ہے۔ اگر override فائل base فائل کے ساتھ موجود ہو تو Compose اسے خود بخود دوسری فائل کے طور پر load کر لیتا ہے۔

ls compose.yaml compose.override.yaml
docker compose up -d

دونوں فائلیں موجود ہوں تو نتیجہ وہی ہوتا ہے جیسے آپ انہیں خود درج کرتے۔

docker compose -f compose.yaml -f compose.override.yaml up -d

Compose جن ناموں کو تسلیم کرتا ہے وہ compose.override.yaml، compose.override.yml، اور پرانے docker-compose.override.yml اور docker-compose.override.yaml ہیں۔ کوئی بھی دوسرا نام، مثلاً compose.dev.yaml، صرف اسی وقت load ہوتا ہے جب آپ اسے -f کے ذریعے نامزد کریں۔

جیسے ہی آپ ایک -f فراہم کرتے ہیں، خودکار loading رک جاتی ہے۔ docker compose -f compose.yaml up صرف اسی ایک فائل کو پڑھتا ہے اور override کو نظر انداز کرتا ہے۔ اسی خاصیت کی بنیاد پر اس guide میں بعد میں dev اور prod pattern بنایا گیا ہے۔

سرور پر اس کے دونوں طرح کے اثرات ہو سکتے ہیں۔ deploy directory میں موجود override فائل اس directory سے چلائے جانے والے ہر سادہ docker compose command کے ذریعے load ہوتی ہے، جس میں cron job چلانے والا command بھی شامل ہے۔ اسی طرح production stack میں ایسی source directory bind-mount ہو سکتی ہے جسے شامل کرنے کا کسی کا ارادہ نہیں تھا۔ ہر deploy کے بعد docker compose config چلائیں اور اس کا output پڑھیں۔ جب deploy unattended ہو تو یہ check صرف اسی صورت میں مفید ہے جب کوئی آپ کو خرابی سے آگاہ کرے۔ یہی کام self-hosted ntfy server جیسے push channel کا ہے، جس پر cron job یا systemd OnFailure unit post کر سکتی ہے۔

-f کے ساتھ ترتیب اور نسبتاً paths کے resolve ہونے کی جگہ

Compose configuration کو ان files کی فراہم کردہ ترتیب کے مطابق بناتا ہے۔ بعد والی files اپنی پیش رو files کی settings کو override کرتی ہیں اور نئی settings شامل کرتی ہیں۔ بائیں سے دائیں چلیں؛ آخری setting نافذ ہوتی ہے۔

docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -d

اس project میں ہر command کو files کی یہی فہرست درکار ہوتی ہے۔ up کو دو files کے ساتھ اور logs کو ایک file کے ساتھ چلانے سے آپ ایک مختلف 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 پہلے سے استعمال نہیں کر رہیں۔ اس کے بجائے فہرست ایک بار COMPOSE_FILE environment variable کے ذریعے مقرر کریں۔

export COMPOSE_FILE=compose.yaml:compose.prod.yaml
docker compose config
docker compose up -d

Linux پر separator : ہے، جبکہ COMPOSE_PATH_SEPARATOR اسے تبدیل کرتا ہے۔ COMPOSE_FILE کو project کی .env file میں بھی رکھا جا سکتا ہے۔ اس طرح یہ آپ کی shell history کے بجائے checkout کا حصہ بن جاتا ہے۔ Command line پر واضح طور پر set کی گئی value environment variable پر فوقیت رکھتی ہے۔

اب اس rule پر غور کریں جو bind mounts کو خراب کر دیتا ہے۔ جب آپ -f کے ساتھ متعدد files استعمال کرتے ہیں تو ان تمام files میں موجود relative paths اس file والی directory کے مطابق resolve ہوتے ہیں جو فہرست میں پہلی ہے، نہ کہ اس file والی directory کے مطابق جس میں path لکھا گیا ہے۔ deploy/prod/compose.prod.yaml کے اندر ./data:/var/lib/postgresql/data لکھنے کے باوجود Compose ./data کو base file کے ساتھ والی directory میں تلاش کرتا ہے۔ Docker پھر اس غلط path پر ایک empty directory بنا دیتا ہے، اور container اس میں موجود data کے بغیر start ہوتا ہے۔ یہ data loss جیسا دکھائی دیتا ہے، لیکن data loss نہیں ہوتا۔ Base path خود مقرر کرنے کے لیے --project-directory دیں، یا include استعمال کریں، جو ہر file کو اس کی اپنی directory کے مطابق resolve کرتا ہے۔

Project name بھی اسی base directory سے حاصل ہوتا ہے۔ اس لیے پہلی file تبدیل کرنے سے project کا نام تبدیل ہو سکتا ہے۔ نئے project name کا مطلب نئے container names اور نئے volume names ہیں، جبکہ پرانا volume پرانے نام کے تحت disk پر موجود رہتا ہے۔ Base file میں top-level name: کے ذریعے project name کو مستقل مقرر کریں۔

name: myapp

کون سے fields merge ہوتے ہیں، اور کون سے replace ہوتے ہیں

Compose value کی type کے مطابق merge کرتا ہے، field کے نام کے مطابق نہیں۔

  • Single-valued fields replace ہوتے ہیں۔ image، command، entrypoint اور mem_limit بعد والی value کو مکمل طور پر اختیار کرتے ہیں۔ command میں ایک argument append نہیں کیا جا سکتا، کیونکہ override پوری line کو دوبارہ لکھ دیتا ہے۔
  • Mappings key کے لحاظ سے merge ہوتے ہیں۔ environment، labels، volumes اور devices دونوں files کی تمام keys برقرار رکھتے ہیں، اور جو key دونوں میں موجود ہو اس کے لیے بعد والی file کی value استعمال ہوتی ہے۔ environment اور labels میں key variable یا label کا نام ہوتی ہے۔ volumes اور devices میں key container path ہوتی ہے۔
  • Sequences append ہوتے ہیں۔ dns، dns_search، expose، tmpfs اور external_links کو باہم جوڑا جاتا ہے۔ expose: ["3000"] رکھنے والی base file کو ["4000", "5000"] رکھنے والے override کے ساتھ merge کرنے سے ["3000", "4000", "5000"] حاصل ہوتا ہے۔

چار sequences میں identity key ہوتی ہے، اس لیے اس key سے match ہونے والی entries append ہونے کے بجائے merge ہوتی ہیں۔ volumes، secrets اور configs میں match target کی بنیاد پر ہوتا ہے۔ ports میں match ip، target، published اور protocol کے مجموعے کی بنیاد پر ہوتا ہے۔

اس ports rule کو دو بار پڑھیں، کیونکہ یہی عام غلطی کا مقام ہے۔ دو port entries اسی وقت ایک ہی entry سمجھی جاتی ہیں جب ان چاروں حصوں کی values یکساں ہوں۔ ان میں سے کسی ایک کو تبدیل کریں تو Compose اسے دوسری، غیر متعلقہ port سمجھتا ہے، اس لیے دونوں entries برقرار رہتی ہیں۔

اووررائٹ کے بعد بھی port شائع کیوں ہے

بنیادی file جو service کو ہر interface پر 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 موجود ہیں۔ ip والا حصہ مختلف ہے، یعنی 0.0.0.0 کے مقابلے میں 127.0.0.1، اس لیے merge کے لحاظ سے یہ دو مختلف ports ہیں، اور جس public binding کو آپ نے ہٹانے کی کوشش کی تھی وہ اب بھی model میں موجود ہے۔ Docker میں یہ مسئلہ دیگر صورتوں کے مقابلے میں زیادہ اہم ہے، کیونکہ published port آپ کے firewall rules سے پہلے iptables میں شامل کر دیا جاتا ہے۔ اس طریقۂ کار کی وضاحت published Docker ports، ufw سے آگے کیوں گزر جاتے ہیں میں کی گئی ہے۔

اس کے دو حل ہیں۔ واضح حل !override tag ہے، جو مکمل attribute کو replace کرتا ہے اور merge rules کو نظرانداز کرتا ہے:

services:
  web:
    ports: !override
      - "127.0.0.1:8080:80"

!override کے لیے Compose v2.24.4 یا اس کے بعد کا ورژن درکار ہے۔ portable حل کے لیے کسی tag کی ضرورت نہیں: ports کو base file سے مکمل طور پر خارج رکھیں اور اسے صرف environment-specific files میں declare کریں۔ Merge کرنے کے لیے کچھ موجود نہ ہو تو leak ہونے کے لیے بھی کچھ نہیں ہوتا۔ نیچے دی گئی عملی مثال میں یہی pattern استعمال کیا گیا ہے۔

بیس فائل میں مقرر کردہ قدر حذف کرنا

!reset کسی attribute کو ہٹا کر اسے اس کی default قدر یا null پر واپس لے آتا ہے۔ یہ ایک قدر لیتا ہے اور اسے نظرانداز کر دیتا ہے، اس لیے کوئی درست اور خالی قدر لکھیں۔

services:
  web:
    ports: !reset []
    environment:
      DEBUG: !reset null

!reset کے لیے Compose v2.24 یا اس کے بعد کا ورژن درکار ہے۔ اسے اس وقت استعمال کریں جب base file میں ترمیم آپ کے اختیار میں نہ ہو، مثلاً جب آپ کسی vendor fragment کو شامل کر رہے ہوں۔ شائع کردہ upstream stack عین ایسی صورت ہے: self-hosted AFFiNE workspace کے پیچھے موجود Compose file میں چار ایسے containers deklar کیے گئے ہیں جنہیں آپ نے خود نہیں لکھا، اور !reset آپ کو ان میں سے کسی ایک کے ایک attribute کو file کی fork بنائے بغیر صاف کرنے دیتا ہے، یوں اس file کی تبدیلیوں کو track کرنے کی ذمہ داری بھی آپ پر نہیں آتی۔

حصوں سے تیار کیے گئے stacks کے لیے include

include ایک اور Compose application کو آپ کے model میں شامل کرتا ہے۔ یہ top-level element ہے، flag نہیں۔

include:
  - path: ../commons/compose.yaml

include میں موجود ہر path کو اس کی اپنی Compose application model کے طور پر load کیا جاتا ہے۔ ہر model کی اپنی project directory ہوتی ہے، اس لیے اس file کے اندر موجود relative paths اسی file کی اپنی directory کے مطابق resolve ہوتے ہیں۔ یہی -f سے اصل فرق ہے، اور اسی وجہ سے include اس وقت درست tool ہے جب fragment کسی دوسرے folder یا repository میں موجود ہو۔ عموماً vendor stack کی ساخت ایسی ہی ہوتی ہے جسے آپ نے خود نہیں لکھا: self-hosted Authentik SSO installation کے پیچھے موجود 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/.env

path ایک list قبول کرتا ہے، اور result کو آپ کے model میں شامل کرنے سے پہلے ان files کو معمول کے rules کے مطابق merge کیا جاتا ہے۔ project_directory included file میں relative paths resolve کرنے کے لیے استعمال ہونے والا base path متعین کرتا ہے۔ env_file included file کو interpolation کے لیے اپنی variables فراہم کرتا ہے۔ اس سے shared fragment خاموشی سے آپ کے project کا .env پڑھنے سے محفوظ رہتا ہے۔ include کے لیے Compose v2.20.0 یا اس کے بعد کا version درکار ہے۔ یہی options اس stack میں single-container add-on شامل کرنے کے لیے بھی موزوں ہیں جسے آپ پہلے سے چلا رہے ہوں، مثلاً Halcyon، جو Jellyfin library کو 90s کے rental store کی شکل دیتا ہے: اس کی file اپنا image tag اور اپنا env_file برقرار رکھتی ہے، اس لیے اسے upgrade کرنے کے لیے آپ کے media stack والی file کو چھیڑنا نہیں پڑتا۔

آپ کی file اور included file کے درمیان duplicate resource names کو خاموشی سے merge کرنے کے بجائے error کے طور پر report کیا جاتا ہے، اور یہ جان بوجھ کر ہے۔ Included file میں declared کسی چیز کو تبدیل کرنے کے لیے تبدیلی compose.override.yaml میں رکھیں: override assembled model پر apply ہوتا ہے، اس لیے وہ included resources کو ان سے ٹکرائے بغیر تبدیل کر سکتا ہے۔ یہ طریقہ خاص طور پر ایسے stack میں مفید ہے جس کی upstream file ہر release پر دوبارہ لکھی جاتی ہو، مثلاً PhotoPrism بمقابلہ Immich میں زیرِ غور multi-container photo servers، جہاں localhost binding یا اضافی volume کو upgrade کے بعد replace ہونے والی file کے بجائے آپ کے override میں ہونا چاہیے۔

مختصر طور پر: include الگ applications کو compose کرتا ہے، جبکہ -f ایک application پر configuration کی تہیں رکھتا ہے۔

ایک VPS پر dev اور prod کی علیحدگی

یہ مکمل طریقہ کار 3 فائلوں میں ہے۔ base فائل ہر جگہ درست configuration بیان کرتی ہے، اور کوئی port publish نہیں کرتی۔

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 شرط کی وجہ سے app ایسے database کا انتظار کرتی ہے جو جواب دے رہا ہو، نہ کہ صرف موجود container کا۔ اس کی وضاحت healthchecks اور depends_on conditions میں ہے۔ POSTGRES_PASSWORD کو project کی .env فائل سے interpolate کیا جاتا ہے، اور یہ فائل کبھی git میں شامل نہیں ہونی چاہیے۔ محفوظ متبادل کے لیے env files اور Compose secrets دیکھیں۔

اس کے بعد compose.override.yaml ہے، جسے Compose خود load کرتا ہے۔ یہ developer کی فائل ہے۔

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"

laptop پر سادہ docker compose up ان دونوں فائلوں کو merge کرتا ہے۔ command image default کو replace کرتا ہے کیونکہ اس کی صرف ایک value ہوتی ہے۔ LOG_LEVEL، info کو replace کرتا ہے کیونکہ environment key کے لحاظ سے merge کرتا ہے۔ bind mount اور publish کیے گئے دونوں ports خالص اضافے ہیں، جبکہ database port کو localhost سے bind کیا گیا ہے تاکہ shared network پر موجود کوئی دوسرا laptop PostgreSQL کو network پر دستیاب نہ دیکھ سکے۔

آخر میں compose.prod.yaml ہے۔ اس کا نام ان ناموں میں شامل نہیں جنہیں Compose تلاش کرتا ہے، اس لیے یہ کبھی اتفاقاً load نہیں ہوتی۔

services:
  app:
    ports:
      - "127.0.0.1:8000:3000"
    deploy:
      resources:
        limits:
          memory: 512M

VPS پر دونوں فائلوں کے نام دیں۔ یہی عمل override کو خارج کرتا ہے۔

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 ps

ps کو دونوں services کو running دکھانا چاہیے، اور db میں (healthy) نظر آنا چاہیے۔ چونکہ آپ نے -f دیا تھا، اس لیے compose.override.yaml نہیں پڑھی گئی۔ چنانچہ dev command، source bind mount اور public port 3000 production تک نہیں پہنچ سکتے، حالانکہ فائل اسی directory میں موجود ہے۔ Port 8000 صرف localhost پر ہے اور proxy کے لیے تیار ہے۔ دوسری service شامل کرتے وقت Traefik کے پیچھے متعدد apps چلانا دیکھیں۔

سرور کی .env میں COMPOSE_FILE=compose.yaml:compose.prod.yaml مقرر کریں۔ اس کے بعد آپ کے باقی commands دوبارہ سادہ docker compose logs -f app بن جائیں گے۔

Single-service stack بھی یہی ساخت اختیار کرتا ہے، کیونکہ self-hosted openGym workout tracker کو پہلے passkey کا اندراج کرنے سے پہلے proxy کے پیچھے TLS کے ذریعے جواب دینا ہوتا ہے۔ ایسی base فائل، جس میں ports نہ ہو، stray public binding کو proxy سے پہلے درخواستیں سنبھالنے سے روکتی ہے۔

تعیناتی سے پہلے merged model پڑھیں

docker compose config مکمل merged اور interpolated model دکھاتا ہے۔ یہ preview نہیں ہے۔ یہی وہ exact 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 names کی فہرست بناتا ہے۔ اس سے فوری طور پر تصدیق ہو جاتی ہے کہ include نے مطلوبہ configuration شامل کی ہے۔

خرابی کی صورتیں اور آپ کو کیا نظر آئے گا

no configuration file provided: not found۔ Compose کو پڑھنے کے لیے کچھ نہیں ملا۔ آپ project directory سے باہر ہیں، یا COMPOSE_FILE ایسے path کی نشاندہی کرتا ہے جو موجود نہیں۔ Compose default base file تلاش کرنے کے لیے parent directories میں دیکھتا ہے، لیکن آپ کے بتائے ہوئے file کو تلاش کرنے کے لیے کسی بھی جگہ نہیں دیکھتا۔

WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string. Interpolation project کی .env file اور shell environment کے مطابق حل ہوتی ہے، اور یہاں project directory پہلی -f file کی directory ہے۔ .env رکھنے والی directory سے مختلف directory میں deployment کرنے پر یہ warning ظاہر ہوتی ہے، اور پھر database کسی بھی connection کو قبول نہیں کرتا۔

آپ کی override میں کی گئی ترمیم docker compose config میں ظاہر نہیں ہوتی۔ یا تو آپ نے -f دیا ہے، جس سے automatic override loading بند ہو جاتی ہے، یا Compose کو parent directory میں compose.yaml مل گئی ہے اور آپ کی override file اس کے ساتھ موجود نہیں۔ docker compose config کو کسی دوسرے argument کے بغیر چلانے سے معلوم ہوتا ہے کہ Compose حقیقت میں کون سا model بنا رہا ہے۔

bind mount خالی ہے اور Docker نے ایسی directory بنا دی ہے جس کی آپ نے درخواست نہیں کی تھی۔ Relative path پہلی file کی directory کے مطابق resolve ہوا۔ Path درست کریں، --project-directory دیں، یا fragment کو include کے پیچھے منتقل کریں۔

Containers نئے ناموں کے ساتھ واپس آتے ہیں اور volume خالی دکھائی دیتا ہے۔ Project name تبدیل ہو گیا، کیونکہ project name پہلی file کی directory کے مطابق ہوتا ہے۔ Base file میں top-level name: شامل کریں؛ اس سے نام تبدیل ہونا بند ہو جائے گا۔ پرانا volume اب بھی پرانے prefix کے تحت موجود ہے، اور docker volume ls اسے دکھا دے گا۔

Override میں ہٹایا گیا port اب بھی کھلا ہے۔ ports merge نے اسے replace کرنے کے بجائے append کر دیا۔ docker compose config سے تصدیق کریں، پھر یا تو !override استعمال کریں یا ports کو base file سے باہر منتقل کریں۔

FAQ

کیا Compose خودکار طور پر compose.override.yaml لوڈ کرتا ہے؟

جی ہاں، جب آپ docker compose کو -f flag کے بغیر چلاتے ہیں۔ Compose working directory اور اس کی parent directories میں compose.yaml یا docker-compose.yaml تلاش کرتا ہے۔ اگر override file اسی directory میں موجود ہو تو اسے دوسرے مرحلے میں لوڈ کیا جاتا ہے۔ تسلیم شدہ نام compose.override.yaml، compose.override.yml، docker-compose.override.yml اور docker-compose.override.yaml ہیں۔ کوئی بھی -f فراہم کرنے سے یہ طرزِ عمل غیر فعال ہو جاتا ہے، اس لیے docker compose -f compose.yaml up صرف ایک file پڑھتا ہے۔

متعدد -f files کس ترتیب سے merge ہوتی ہیں؟

بائیں سے دائیں۔ Compose آپ کی فراہم کردہ files کی ترتیب کے مطابق configuration تیار کرتا ہے۔ ہر file اپنے سے پہلے والی files کی settings کو override یا ان میں اضافہ کرتی ہے، اس لیے کسی conflict میں command line کی آخری file غالب آتی ہے۔ اس project کی ہر command کے لیے یہی فہرست استعمال ہونی چاہیے۔ اسی مقصد کے لیے COMPOSE_FILE=compose.yaml:compose.prod.yaml موجود ہے۔

Override کے بعد بھی میرا port published کیوں ہے؟

کیونکہ ports entries کی شناخت ip، target، published اور protocol کے مکمل مجموعے سے ہوتی ہے۔ 8080:80 کی base کے مقابل 127.0.0.1:8080:80 کا override ip حصے میں مختلف ہے۔ اس لیے Compose اسے دوسرے port کے طور پر لیتا ہے اور دونوں برقرار رکھتا ہے۔ docker compose config چلانے پر آپ کو دونوں entries نظر آئیں گی۔ Compose v2.24.4 یا اس کے بعد کے ورژن میں ports: !override استعمال کریں، یا base file سے ports نکال دیں تاکہ merge کرنے کے لیے کوئی entry موجود نہ ہو۔

include اور -f میں کیا فرق ہے؟

-f متعدد files کو ایک application کے لیے layer کرتا ہے، اور ہر file میں موجود relative path پہلی file کی directory کے لحاظ سے resolve ہوتا ہے۔ include ایک الگ Compose application شامل کرتا ہے، اور ہر شامل کی گئی path اپنی project directory برقرار رکھتی ہے۔ اس لیے اس کے relative paths اسی application کے لحاظ سے resolve ہوتے ہیں۔ اپنی stack کی environment layers کے لیے -f استعمال کریں، اور کہیں اور maintain کیے جانے والے fragment کے لیے include استعمال کریں۔ include کے لیے Compose v2.20.0 یا اس کے بعد کا ورژن درکار ہے۔

Base file کی مقرر کردہ value کیسے ہٹاؤں؟

Compose v2.24 یا اس کے بعد کے ورژن میں !reset tag استعمال کریں۔ Overriding file میں ports: !reset [] یا MY_VAR: !reset null لکھیں۔ اس سے attribute اپنی default value یا null پر واپس آ جاتا ہے۔ Tag کو دی جانے والی value لازمی ہے، لیکن اسے نظرانداز کیا جاتا ہے۔ اگر آپ کسی attribute کو خالی کرنے کے بجائے اس کی جگہ نئی value رکھنا چاہتے ہیں تو !override یہ کام کرتا ہے، اور اس کے لیے v2.24.4 یا اس کے بعد کا ورژن درکار ہے۔