Docker Compose میں متعدد فائلیں کیسے merge ہوتی ہیں؟
جانیں %%C24%% کے بغیر %%C23%% کیسے %%C25%% لوڈ کرتا ہے، فائلوں کی ترتیب کیا بدلتی ہے، ports کیوں کھلا رہتا ہے، اور dev و prod کے لیے %%C18%% کیسے کام کرتا ہے۔
Compose ایک سے زیادہ فائلوں کے ساتھ کیا کرتا ہے
Docker Compose کئی فائلوں سے ایک project بنا سکتا ہے۔ یہ فائلوں کو موصول ہونے کی ترتیب میں پڑھتا ہے اور انہیں ایک واحد model میں merge کرتا ہے، اس لیے بعد والی فائل متصادم value پر ترجیح پاتی ہے۔ کمانڈ لائن سے یہ کام کرنے کے دو طریقے ہیں: ایک override file جسے 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 file نہیں لکھی، تو Docker Compose کی بنیادی معلومات کی رہنما سے شروع کریں اور پھر واپس آئیں۔
وہ override فائل جسے Compose بتائے بغیر لوڈ کرتا ہے
-f flag کے بغیر docker compose up چلانے پر Compose پہلے working 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 فراہم کرتے ہیں، خودکار لوڈنگ رک جاتی ہے۔ docker compose -f compose.yaml up صرف اسی ایک فائل کو پڑھتا ہے اور override کو نظرانداز کرتا ہے۔ اسی خاصیت کی بنیاد پر اس رہنما میں بعد میں dev اور prod کا طریقہ بنایا گیا ہے۔
سرور پر اس کے دونوں طرح کے نتائج ہو سکتے ہیں۔ deploy directory میں موجود override file اس directory سے چلنے والی ہر سادہ docker compose command کے ذریعے لوڈ ہوتی ہے، اس command سمیت جسے آپ کا cron job چلاتا ہے۔ اسی طرح production stack ایسی source directory کو bind-mount کر دیتا ہے جسے شامل کرنے کا کسی کا ارادہ نہیں تھا۔ ہر deploy کے بعد docker compose config چلائیں اور اس کا نتیجہ پڑھیں۔
C کے ساتھ ترتیب، اور نسبتاً راستوں کا حل ہونا
Compose کنفیگریشن کو ان فائلوں کی فراہم کردہ ترتیب میں بناتا ہے، اور بعد والی فائلیں اپنی پیش رو فائلوں کی ترتیبات کو override کرتی ہیں اور نئی ترتیبات شامل کرتی ہیں۔ بائیں سے دائیں، آخری ترتیب نافذ ہوتی ہے۔
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -dاس project میں ہر command کے لیے فائلوں کی یہی فہرست درکار ہوتی ہے۔ up کو دو فائلوں کے ساتھ اور logs کو ایک فائل کے ساتھ چلانے سے آپ مختلف merged model کے ساتھ کام کر رہے ہوتے ہیں۔ اس طرح کسی ایسی service کا مسئلہ پیدا ہو سکتا ہے جس کے بارے میں Compose کہتا ہے کہ وہ موجود نہیں ہے۔ اس کے بجائے COMPOSE_FILE environment variable کے ذریعے فہرست ایک بار متعین کریں۔
export COMPOSE_FILE=compose.yaml:compose.prod.yaml
docker compose config
docker compose up -dLinux پر separator : ہے، جبکہ COMPOSE_PATH_SEPARATOR اسے تبدیل کرتا ہے۔ COMPOSE_FILE project کی .env فائل میں بھی رکھا جا سکتا ہے۔ اس طرح یہ آپ کی shell history کے بجائے checkout کا حصہ بن جاتا ہے۔ command line پر واضح طور پر مقرر کی گئی کوئی بھی قدر environment variable پر مقدم ہوتی ہے۔
اب وہ rule جو bind mounts کو متاثر کرتا ہے۔ جب آپ -f کے ساتھ متعدد فائلیں استعمال کرتے ہیں، تو ان تمام فائلوں کے تمام relative paths پہلی فائل کی directory کے مطابق resolve ہوتے ہیں، نہ کہ اس فائل کے مطابق جس میں وہ paths موجود ہیں۔ deploy/prod/compose.prod.yaml کے اندر ./data:/var/lib/postgresql/data لکھنے پر بھی Compose ./data کو base file کے ساتھ تلاش کرتا ہے۔ Docker پھر اس غلط path پر ایک خالی directory بنا دیتا ہے، اور container اس میں موجود data کے بغیر شروع ہوتا ہے۔ یہ data loss جیسا دکھائی دیتا ہے، لیکن حقیقت میں ایسا نہیں ہوتا۔ base path خود متعین کرنے کے لیے --project-directory پاس کریں، یا include استعمال کریں، جو ہر فائل کے paths کو اسی فائل کی اپنی directory کے مطابق resolve کرتا ہے۔
project name اسی base directory سے حاصل ہوتا ہے، اس لیے پہلی فائل تبدیل کرنے سے project کا نام بدل سکتا ہے۔ project کا نام بدلنے سے نئے container names اور نئے volume names بن جاتے ہیں، جبکہ پرانا volume پرانے نام کے تحت disk پر موجود رہتا ہے۔ base file میں top-level name: کے ذریعے نام کو مستقل مقرر کریں۔
name: myappکون سے فیلڈز ضم ہوتے ہیں، اور کون سے تبدیل ہوتے ہیں
Compose فیلڈ کے نام کے بجائے اس کی قدر کی قسم کے مطابق انضمام کرتا ہے۔
- واحد قدر والے فیلڈز تبدیل ہو جاتے ہیں۔
image،command،entrypointاورmem_limitبعد والی قدر کو مکمل طور پر اختیار کرتے ہیں۔commandمیں ایک دلیل شامل نہیں کی جا سکتی، کیونکہ override پوری لائن کو دوبارہ لکھ دیتا ہے۔ - میپنگز کلید بہ کلید ضم ہوتی ہیں۔
environment،labels،volumesاورdevicesدونوں فائلوں کی تمام کلیدیں برقرار رکھتے ہیں، اور دونوں میں موجود کسی کلید کی صورت میں بعد والی فائل کی قدر استعمال ہوتی ہے۔environmentاورlabelsکے لیے کلید variable یا label کا نام ہے۔volumesاورdevicesکے لیے کلید container path ہے۔ - تسلسل کے عناصر آخر میں شامل ہوتے ہیں۔
dns،dns_search،expose،tmpfsاورexternal_linksکو جوڑ دیا جاتا ہے۔expose: ["3000"]رکھنے والی base کو["4000", "5000"]رکھنے والے override کے ساتھ ضم کرنے سے["3000", "4000", "5000"]حاصل ہوتا ہے۔
چار تسلسل شناختی کلید رکھتے ہیں، اس لیے اس کلید سے مماثل entries آخر میں شامل ہونے کے بجائے ضم ہوتی ہیں۔ volumes، secrets اور configs، target کی بنیاد پر مماثلت کرتے ہیں۔ ports، ip، target، published اور protocol کے مجموعے کی بنیاد پر مماثلت کرتا ہے۔
ports کے اس اصول کو دو بار پڑھیں، کیونکہ یہی عام غلطی کا سبب بنتا ہے۔ دو port entries صرف اسی وقت ایک ہی entry سمجھی جاتی ہیں جب ان چاروں حصوں میں یکسانیت ہو۔ ان میں سے کسی ایک حصے کو تبدیل کریں تو Compose اسے دوسری، غیر متعلقہ port سمجھتا ہے، اس لیے دونوں entries برقرار رہتی ہیں۔
override کے بعد آپ کا port اب بھی public کیوں ہے
ایک 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 میں درج کیا جاتا ہے۔ اس طریقۂ کار کی وضاحت 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 یا اس کے بعد کا ورژن درکار ہے۔ قابلِ انتقال حل کے لیے کسی tag کی ضرورت نہیں: ports کو base file سے مکمل طور پر خارج رکھیں اور اسے صرف environment-specific files میں declare کریں۔ Merge کرنے کے لیے کچھ موجود نہ ہو تو افشا ہونے کے لیے بھی کچھ موجود نہیں ہوتا۔ ذیل میں موجود عملی مثال میں یہی pattern استعمال کیا گیا ہے۔
بنیادی فائل میں متعین قدر حذف کرنا
!reset کسی attribute کو حذف کرتا ہے اور اسے اس کی default قدر یا null پر واپس لے آتا ہے۔ یہ ایک قدر لیتا ہے لیکن اسے نظرانداز کر دیتا ہے، اس لیے کوئی درست اور خالی قدر لکھیں۔
services:
web:
ports: !reset []
environment:
DEBUG: !reset null!reset کے لیے Compose v2.24 یا اس کے بعد کا ورژن درکار ہے۔ اسے اس وقت استعمال کریں جب بنیادی فائل میں ترمیم کرنا آپ کے اختیار میں نہ ہو، مثلاً جب وہ کسی vendor کا شامل کیا گیا fragment ہو۔
حصوں سے تیار کردہ اسٹیکس کے لیے include
include آپ کے ماڈل میں ایک اور Compose ایپلیکیشن شامل کرتا ہے۔ یہ اعلیٰ سطح کا عنصر ہے، flag نہیں۔
include:
- path: ../commons/compose.yamlinclude میں موجود ہر path کو اس کے اپنے project directory کے ساتھ ایک الگ Compose ایپلیکیشن ماڈل کے طور پر load کیا جاتا ہے۔ اس لیے اس file کے اندر موجود relative paths اسی file کی اپنی directory کے لحاظ سے resolve ہوتے ہیں۔ یہی -f سے اصل فرق ہے، اور اسی وجہ سے include اس وقت درست tool ہے جب fragment کسی دوسرے folder یا repository میں موجود ہو۔
Long form میں ذیلی اختیارات ہوتے ہیں۔
include:
- path:
- ../monitoring/compose.yaml
- ../monitoring/compose.vps.yaml
project_directory: ../monitoring
env_file: ../monitoring/.envpath ایک list قبول کرتا ہے، اور نتیجہ آپ کے model میں شامل ہونے سے پہلے ان files کو معمول کے rules کے مطابق باہم merge کیا جاتا ہے۔ project_directory اس base path کو مقرر کرتا ہے جسے included file کے relative paths resolve کرنے کے لیے استعمال کیا جاتا ہے۔ env_file included file کو interpolation کے لیے اپنے variables فراہم کرتا ہے۔ اس سے shared fragment آپ کے project کے .env کو خاموشی سے پڑھنے سے محفوظ رہتا ہے۔ include کے لیے Compose v2.20.0 یا اس کے بعد کا ورژن درکار ہے۔
آپ کی file اور included file کے درمیان duplicate resource names کو خاموشی سے merge کرنے کے بجائے error کے طور پر report کیا جاتا ہے، اور یہ دانستہ ہے۔ included file میں declare کی گئی کسی چیز کو تبدیل کرنے کے لیے تبدیلی compose.override.yaml میں رکھیں۔ override assembled model پر لاگو ہوتا ہے، اس لیے یہ included resources سے ٹکرائے بغیر ان میں تبدیلی کر سکتا ہے۔
مختصر طور پر: include الگ الگ applications کو compose کرتا ہے، جبکہ -f ایک ہی application پر configuration کی تہیں لگاتا ہے۔
ایک VPS پر dev اور prod کی علیحدگی
یہ پورا طریقہ تین فائلوں میں ہے۔ بنیادی فائل میں ہر جگہ درست رہنے والی ترتیبات بیان کی گئی ہیں، اور یہ کوئی بھی port شائع نہیں کرتی۔
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 فائل سے interpolated کیا جاتا ہے، اور یہ فائل کبھی 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 value کو replace کرتا ہے کیونکہ اس کی صرف ایک value ہوتی ہے۔ LOG_LEVEL، info کو replace کرتا ہے کیونکہ environment key کے لحاظ سے merge ہوتا ہے۔ bind mount اور شائع کیے گئے دونوں ports صرف اضافے ہیں۔ database port صرف localhost سے bind ہے، اس لیے shared network پر موجود laptop PostgreSQL کو دوسرے لوگوں کے لیے دستیاب نہیں کرتا۔
آخر میں compose.prod.yaml ہے۔ Compose اس نام والی فائل تلاش نہیں کرتا، اس لیے یہ کبھی اتفاقاً load نہیں ہوتی۔
services:
app:
ports:
- "127.0.0.1:8000:3000"
deploy:
resources:
limits:
memory: 512MVPS پر آپ دونوں فائلوں کے نام دیتے ہیں، اور یہی عمل 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 psps کو دونوں services کو running دکھانا چاہیے، اور db میں (healthy) ظاہر ہونا چاہیے۔ چونکہ آپ نے -f دیا تھا، اس لیے compose.override.yaml کو read نہیں کیا گیا۔ نتیجتاً dev command، source bind mount اور public port 3000 production تک نہیں پہنچ سکتے، اگرچہ فائل اسی directory میں موجود ہے۔ Port 8000 صرف localhost پر دستیاب ہے اور proxy کے لیے تیار ہے۔ دوسرا service شامل کرتے وقت Traefik کے پیچھے متعدد apps چلانا دیکھیں۔
Server کے .env میں COMPOSE_FILE=compose.yaml:compose.prod.yaml مقرر کریں۔ اس کے بعد آپ کے باقی commands دوبارہ سادہ docker compose logs -f app بن جائیں گے۔
تعیناتی سے پہلے 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} کو expand نہیں کرتا۔ 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 کی بنیاد پر resolve ہوتی ہے، اور یہاں project directory پہلی -f file کی directory ہے۔ .env رکھنے والی directory کے بجائے کسی دوسری directory سے deploy کرنے پر یہ warning ظاہر ہوتی ہے، اور اس کے بعد database ہر connection مسترد کرتا ہے۔
آپ کی override edit، docker compose config میں نظر نہیں آتی۔ یا تو آپ نے -f دیا ہے، جس سے automatic override loading بند ہو جاتی ہے، یا Compose کو parent directory میں compose.yaml مل گئی ہے اور آپ کی override file اس کے ساتھ موجود نہیں۔ کوئی دوسرا argument دیے بغیر docker compose config چلانے سے معلوم ہو جاتا ہے کہ 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 یا ان میں اضافہ کرتی ہے۔ اس لیے line کے آخر میں موجود file کسی بھی conflict میں غالب آتی ہے۔ اس project کی ہر command کے لیے یہی فہرست استعمال ہونی چاہیے۔ اسی مقصد کے لیے COMPOSE_FILE=compose.yaml:compose.prod.yaml موجود ہے۔
override کرنے کے بعد بھی میرا port published کیوں ہے؟
کیونکہ ports entries کی شناخت ip، target، published اور protocol کے مکمل مجموعے سے ہوتی ہے۔ 127.0.0.1:8080:80 کے override کو 8080:80 کی base کے مقابل رکھنے سے ip حصہ مختلف ہو جاتا ہے۔ اس لیے Compose اسے دوسرا port سمجھتا ہے اور دونوں برقرار رکھتا ہے۔ docker compose config چلانے پر آپ کو دونوں entries نظر آئیں گی۔ Compose v2.24.4 یا اس کے بعد کے ورژن میں ports: !override استعمال کریں۔ متبادل طور پر ports کو base file سے نکال دیں، تاکہ merge کرنے کے لیے کوئی اندراج موجود نہ ہو۔
include اور -f میں کیا فرق ہے؟
-f متعدد files کو ایک application پر layers کی صورت میں لاگو کرتا ہے۔ ہر file میں موجود ہر relative path کی resolution پہلی file کی directory کے نسبت سے ہوتی ہے۔ include ایک الگ Compose application شامل کرتا ہے۔ شامل کی گئی application کے paths اپنی 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 کو صاف کرنے کے بجائے تبدیل کرنا چاہتے ہیں تو !override یہ کام کرتا ہے، اور اس کے لیے v2.24.4 یا اس کے بعد کا ورژن درکار ہے۔