آموزش استفاده از چندین فایل در Docker Compose
نحوه ادغام فایلهای compose.yaml و compose.override.yaml را بیاموزید. با اولویتبندی فایلها، رفع خطای پورتها و مدیریت جداگانه محیطهای توسعه و تولید در Docker Compose v2 آشنا شوید.
نحوه عملکرد Docker Compose با بیش از یک فایل
Docker Compose میتواند یک پروژه را از چندین فایل بسازد. این ابزار فایلها را به ترتیبی که دریافت میکند میخواند و آنها را در یک مدل واحد ادغام میکند؛ بنابراین در صورت وجود مقادیر متناقض، فایلی که دیرتر خوانده شده است اولویت دارد. دو مکانیزم برای انجام این کار از طریق خط فرمان وجود دارد: یک فایل override که Compose بهطور خودکار بارگذاری میکند، و فلگ -f که شما بهصورت دستی وارد میکنید. مکانیزم سوم در داخل خود فایل قرار دارد، یعنی المان include، که عملکرد آن با دو مورد دیگر متفاوت است.
این ادغام یک جایگزینی ساده نیست. نگاشتها (mappings) کلید به کلید ادغام میشوند، دنبالهها (sequences) به انتهای یکدیگر اضافه میشوند و تعداد کمی از فیلدها بهطور کامل جایگزین میشوند. همین تفاوت منشأ غافلگیریهاست و لیست ports موردی است که تقریباً همه را به اشتباه میاندازد.
تمام موارد زیر فرض را بر استفاده از Compose v2 میگذارند، یعنی پلاگین docker compose به جای اسکریپت قدیمی docker-compose. برای بررسی، دستور docker compose version را اجرا کنید. اگر هنوز فایل Compose ننوشتهاید، با راهنمای مقدماتی Docker Compose شروع کنید و سپس به اینجا بازگردید.
فایل override که Compose بدون دستور خاصی بارگذاری میکند
اگر docker compose up را بدون هیچ پرچم -f اجرا کنید، Compose دایرکتوری جاری و سپس دایرکتوریهای والد آن را برای یافتن compose.yaml یا docker-compose.yaml جستجو میکند. اگر یک فایل override در کنار فایل پایه قرار داشته باشد، Compose آن را به صورت خودکار و به عنوان فایل دوم بارگذاری میکند.
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، تنها زمانی بارگذاری میشود که آن را با -f مشخص کنید.
به محض اینکه یک -f را وارد کنید، بارگذاری خودکار متوقف میشود. docker compose -f compose.yaml up دقیقاً همان یک فایل را میخواند و فایل override را نادیده میگیرد؛ این همان ویژگی است که الگوی توسعه (dev) و تولید (prod) در ادامه این راهنما بر پایه آن بنا شده است.
این موضوع در سرور میتواند هر دو نتیجه را داشته باشد. فایل override که در دایرکتوری deploy باقی مانده است، با هر فرمان بدون آرگومان docker compose که از همان دایرکتوری اجرا شود بارگذاری میشود؛ از جمله فرمانی که cron job شما اجرا میکند. به این ترتیب، یک stack production در نهایت دایرکتوری sourceای را با bind mount متصل میکند که قرار نبود کسی آن را منتشر کند. پس از هر deploy، docker compose config را اجرا کنید و خروجی آن را بخوانید. وقتی deploy بدون نظارت اجرا میشود، این بررسی فقط زمانی مفید است که چیزی به شما اطلاع دهد مشکلی رخ داده است. این وظیفه را یک کانال push مانند سرور ntfy خودمیزبان انجام میدهد که cron job یا یک unit از نوع systemd OnFailure میتواند به آن پیام ارسال کند.
ترتیب با -f و محل حل مسیرهای نسبی
Compose پیکربندی را به ترتیبی که فایلها را ارائه میدهید میسازد و فایلهای بعدی، فایلهای قبلی را بازنویسی کرده یا به آنها اضافه میشوند. از چپ به راست، آخرین فایل اولویت دارد.
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -dهر دستوری در آن پروژه به همان لیست فایل نیاز دارد. اگر up را با دو فایل و logs را با یک فایل اجرا کنید، در حال تعامل با یک مدل ادغامشدهٔ متفاوت هستید؛ این روشی سریع برای رسیدن به سرویسی است که Compose میگوید وجود ندارد. ریسک این کار در stackهایی که ارتقای آنها به صورت دستورات تکمرحلهای (one-off) انجام میشود، افزایش مییابد؛ برای مثال در مرحلهٔ مهاجرت دیتابیس در یک میز پشتیبانی Chatwoot خودمیزبان، اگر دستور docker compose run با لیست فایل اشتباه صادر شود، بیسروصدا مدلی متفاوت از آنچه سرویسهای شما در حال حاضر استفاده میکنند را هدف قرار میدهد. در عوض، لیست را یکبار با متغیر محیطی COMPOSE_FILE تنظیم کنید.
export COMPOSE_FILE=compose.yaml:compose.prod.yaml
docker compose config
docker compose up -dجداکننده در لینوکس : است و COMPOSE_PATH_SEPARATOR آن را تغییر میدهد. COMPOSE_FILE همچنین میتواند در فایل .env پروژه قرار بگیرد که باعث میشود بخشی از checkout باشد، نه بخشی از تاریخچهٔ shell شما. هر چیزی که صراحتاً در خط فرمان تنظیم شود، بر متغیر محیطی غلبه میکند.
حال قانونی که bind mountها را مختل میکند: هنگامی که از چندین فایل با -f استفاده میکنید، تمام مسیرهای نسبی در همهٔ آن فایلها نسبت به دایرکتوری اولین فایل حل میشوند، نه نسبت به فایلی که حاوی آنهاست. اگر ./data:/var/lib/postgresql/data را داخل deploy/prod/compose.prod.yaml بنویسید، Compose همچنان به دنبال ./data در کنار فایل پایه میگردد. سپس Docker یک دایرکتوری خالی در آن مسیر اشتباه ایجاد میکند و container بدون هیچ محتوایی شروع به کار میکند؛ این وضعیت شبیه به از دست رفتن داده است اما در واقع چنین نیست. برای تنظیم دستی مسیر پایه، --project-directory را ارسال کنید یا از include استفاده کنید که هر فایل را نسبت به دایرکتوری خودش حل میکند.
نام پروژه از همان دایرکتوری پایه گرفته میشود، بنابراین تغییر فایلی که در ابتدا قرار دارد میتواند نام پروژه را تغییر دهد. تغییر نام پروژه به معنای نامهای جدید برای containerها و volumeها است و volume قدیمی همچنان با نام قبلی روی دیسک باقی میماند. به جای آن، با استفاده از یک name: در سطح بالا در فایل پایه، آن را ثابت کنید.
name: myappکدام فیلدها ادغام و کدامیک جایگزین میشوند
Compose ادغام را بر اساس نوع مقدار انجام میدهد، نه نام فیلد.
- فیلدهای تکمقداری جایگزین میشوند.
image،command،entrypointوmem_limitمقدار بعدی را بهطور کامل جایگزین مقدار قبلی میکنند. شما نمیتوانید یک آرگومان را بهcommandاضافه کنید، زیرا override کل خط را بازنویسی میکند. - نگاشتها (Mappings) کلید به کلید ادغام میشوند.
environment،labels،volumesوdevicesتمام کلیدها را از هر دو فایل حفظ میکنند و در صورت وجود کلید مشترک در هر دو فایل، مقدار فایل دوم اولویت دارد. برایenvironmentوlabels، کلید همان نام متغیر یا برچسب (label) است. برایvolumesوdevices، کلید همان مسیر داخل container است. - دنبالهها (Sequences) به یکدیگر متصل میشوند.
dns،dns_search،expose،tmpfsوexternal_linksبه هم الحاق میشوند. یک فایل پایه که حاویexpose: ["3000"]است، پس از ادغام با یک override که حاوی["4000", "5000"]است، نتیجهای شامل["3000", "4000", "5000"]ایجاد میکند.
چهار دنباله دارای یک کلید شناسایی هستند، بنابراین ورودیهایی که با آن کلید مطابقت دارند، بهجای الحاق شدن، با هم ادغام میشوند. volumes، secrets و configs بر اساس target مطابقت داده میشوند. ports بر اساس ترکیب ip، target، published و protocol مطابقت داده میشود.
این قانون ports را دو بار بخوانید، زیرا این همان جایی است که ممکن است دچار اشتباه شوید. دو ورودی پورت تنها زمانی یک ورودی واحد محسوب میشوند که هر چهار بخش آنها با هم مطابقت داشته باشند. اگر حتی یکی از آنها را تغییر دهید، Compose آن را به عنوان یک پورت دوم و نامرتبط میبیند و هر دو را حفظ میکند.
چرا پورت شما پس از override همچنان منتشر میشود
یک فایل پایه که سرویس را روی تمام رابطها منتشر میکند:
services:
web:
image: nginx:1.27
ports:
- "8080:80"یک override که برای bind کردن آن فقط روی localhost نوشته شده است، زیرا قرار است یک reverse proxy جلوی آن قرار بگیرد:
services:
web:
ports:
- "127.0.0.1:8080:80"پیش از آنکه فرض کنید تنظیمات اعمال شده است، نتیجه را بررسی کنید.
docker compose -f compose.yaml -f compose.prod.yaml configهر دو ورودی در خروجی ظاهر میشوند. بخش ip متفاوت است، 0.0.0.0 در مقابل 127.0.0.1، بنابراین از نظر فرآیند ادغام (merge)، اینها دو پورت متفاوت هستند و binding عمومی که سعی داشتید حذف کنید، همچنان در مدل باقی مانده است. این موضوع در Docker اهمیت بیشتری نسبت به سایر موارد دارد، زیرا پورت منتشرشده پیش از قوانین فایروال شما در iptables نوشته میشود. این مکانیزم در چرا پورتهای منتشرشده Docker از ufw عبور میکنند پوشش داده شده است.
دو راه حل وجود دارد. راه حل صریح، استفاده از تگ !override است که کل ویژگی را جایگزین کرده و از قوانین ادغام صرفنظر میکند:
services:
web:
ports: !override
- "127.0.0.1:8080:80"!override به نسخه Compose v2.24.4 یا جدیدتر نیاز دارد. راه حل قابلحمل نیازی به هیچ تگی ندارد: ports را بهطور کامل از فایل پایه حذف کنید و آن را فقط در فایلهای مخصوص محیط (environment-specific) تعریف کنید. وقتی چیزی برای ادغام وجود نداشته باشد، چیزی هم نشت نمیکند. این همان الگویی است که در مثال عملی زیر استفاده شده است.
حذف یک مقدار از مجموعه فایل پایه
!reset یک ویژگی را حذف میکند و آن را به مقدار پیشفرض یا null بازمیگرداند. این دستور یک مقدار را میگیرد اما از آن صرفنظر میکند، بنابراین یک مقدار معتبر و خالی بنویسید.
services:
web:
ports: !reset []
environment:
DEBUG: !reset null!reset به نسخه 2.24 یا جدیدتر Compose نیاز دارد. زمانی از آن استفاده کنید که فایل پایه متعلق به شما نیست و امکان ویرایش آن را ندارید؛ برای مثال، یک قطعهکد (fragment) از فروشنده که آن را فراخوانی میکنید. یک استک منتشرشده توسط توسعهدهنده اصلی دقیقاً همین مورد است: فایل Compose مربوط به یک فضای کاری AFFiNE خودمیزبان چهار کانتینر را تعریف میکند که شما آنها را ننوشتهاید، و !reset به شما اجازه میدهد یک ویژگی را از یکی از آنها پاک کنید، بدون اینکه نیاز باشد فایل را فورک کنید و مسئولیت پیگیری تغییرات آن را بر عهده بگیرید.
include، برای پشتههایی که از بخشهای مختلف تشکیل شدهاند
include یک اپلیکیشن Compose دیگر را به مدل شما وارد میکند. این یک عنصر سطح بالا (top-level) است، نه یک فلگ.
include:
- path: ../commons/compose.yamlهر مسیر در include به عنوان مدل اپلیکیشن Compose اختصاصی خود بارگذاری میشود و دایرکتوری پروژه مخصوص به خود را دارد؛ بنابراین مسیرهای نسبی درون آن فایل، نسبت به دایرکتوری همان فایل حل میشوند. این تفاوت اصلی با -f است و به همین دلیل include ابزار مناسبی برای زمانی است که قطعه کد در پوشه یا مخزن دیگری قرار دارد. این شکل معمول برای پشتههای آمادهای (vendor stack) است که شما ننوشتهاید: فایل Compose چندسرویسیِ مربوط به نصب Authentik SSO به صورت self-hosted میتواند در دایرکتوری خودش با مسیرهای نسبی دستنخورده باقی بماند، در حالی که فایل شما همچنان بر سرویسهای خودتان متمرکز است.
فرم طولانی این دستور، زیر-گزینههایی را میپذیرد.
include:
- path:
- ../monitoring/compose.yaml
- ../monitoring/compose.vps.yaml
project_directory: ../monitoring
env_file: ../monitoring/.envpath یک لیست را میپذیرد و آن فایلها پیش از پیوستن به مدل شما، طبق قوانین استاندارد با هم ادغام میشوند. project_directory مسیر پایه مورد استفاده برای حل مسیرهای نسبی در فایلِ واردشده را تعیین میکند. env_file متغیرهای اختصاصی برای جایگذاری (interpolation) در اختیار فایل واردشده قرار میدهد که مانع از آن میشود که یک قطعه کد مشترک، بهطور ناخواسته .env پروژه شما را بخواند. include به نسخه 2.20.0 یا جدیدتر Compose نیاز دارد. همین گزینهها برای افزودن یک کانتینرِ جانبی به پشتهای که در حال اجرا دارید نیز مناسب است؛ برای مثال Halcyon که ظاهر کتابخانه Jellyfin را به شکل فروشگاههای کرایه فیلم دهه 90 تغییر میدهد: فایل آن، تگ image و env_file مخصوص به خود را حفظ میکند، بنابراین ارتقای آن هرگز به معنای دستکاری فایلی که پشته رسانهای شما در آن قرار دارد، نخواهد بود.
نامهای تکراری منابع بین فایل شما و فایل واردشده، به جای ادغام بیسروصدا، به عنوان خطا گزارش میشوند و این یک رفتار عمدی است. برای تغییر چیزی که در فایل واردشده تعریف شده، تغییرات را در compose.override.yaml قرار دهید: این override روی مدل نهایی اعمال میشود، بنابراین میتواند منابع واردشده را بدون تداخل با آنها تغییر دهد. این عادت بهویژه در پشتههایی که فایل upstream آنها در هر release بازنویسی میشود، بسیار مفید است؛ مانند سرورهای عکس چندکانتینری که در مقایسه PhotoPrism و Immich بررسی شدهاند، جایی که یک binding روی localhost یا یک volume اضافی باید در override شما باشد، نه در فایلی که در ارتقای بعدی جایگزین خواهد شد.
خلاصه مطلب: include اپلیکیشنهای مجزا را ترکیب میکند، -f پیکربندیها را روی یک اپلیکیشن لایهبندی میکند.
جداسازی محیط توسعه و عملیاتی روی یک VPS
الگوی کامل این کار در سه فایل زیر آمده است. فایل پایه، آنچه را که در همه جا صادق است تعریف میکند و هیچ پورتی را منتشر نمیکند.
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 and depends_on conditions آمده است. مقدار POSTGRES_PASSWORD از فایل .env پروژه جایگذاری میشود که نباید هرگز در git قرار گیرد. برای روشهای امنتر، env files and Compose secrets را ببینید.
سپس فایل 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 جایگزین پیشفرض image میشود زیرا یک مقدار واحد است. مقدار LOG_LEVEL جایگزین info میشود زیرا environment بر اساس کلید ادغام میشود. bind mount و دو پورت منتشرشده، صرفاً افزودنی هستند و پورت دیتابیس به localhost محدود شده است تا لپتاپ در یک شبکه مشترک، سرویس PostgreSQL را در دسترس دیگران قرار ندهد.
در نهایت، فایل compose.prod.yaml قرار دارد. نام این فایل بهگونهای نیست که Compose بهطور خودکار آن را جستجو کند، بنابراین هرگز بهاشتباه بارگذاری نمیشود.
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 باید هر دو سرویس را در حال اجرا نشان دهد و db مقدار (healthy) را نمایش دهد. از آنجا که شما -f را ارسال کردید، فایل compose.override.yaml خوانده نشد؛ بنابراین دستور توسعه، source bind mount و پورت عمومی 3000 نمیتوانند به محیط عملیاتی نفوذ کنند، حتی اگر فایل در همان دایرکتوری موجود باشد. پورت 8000 فقط روی localhost در دسترس است و برای یک پروکسی آماده است: هنگام افزودن سرویس دوم، running several apps behind Traefik را ببینید.
مقدار COMPOSE_FILE=compose.yaml:compose.prod.yaml را در فایل .env سرور تنظیم کنید تا بقیه دستورات شما دوباره به حالت ساده docker compose logs -f app بازگردند.
یک استک تکسرویسی نیز همین ساختار را میطلبد، زیرا a self-hosted openGym workout tracker باید پیش از ثبت اولین passkey، از طریق TLS و پشت یک پروکسی پاسخگو باشد. یک فایل پایه بدون ports در آن، همان چیزی است که مانع از آن میشود که یک binding عمومی ناخواسته، پیش از پروکسی، درخواستها را دریافت کند.
پیش از استقرار، مدل ادغامشده را مطالعه کنید
docker compose config مدل کاملاً ادغامشده و درونیابیشده را چاپ میکند. این یک پیشنمایش نیست. این دقیقاً همان ورودی است که Compose بر اساس آن عمل خواهد کرد؛ بنابراین اگر خروجی با انتظارات شما مغایرت دارد، خروجی صحیح است.
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} گسترش نیابد. پیش از کپی کردن خروجی در هر جایی از این گزینه استفاده کنید، زیرا config ساده، تمام secretهای حلشده را به صورت متن ساده (clear text) چاپ میکند. --services فقط نام سرویسها را فهرست میکند که روشی سریع برای تأیید این است که یک include، آنچه انتظار داشتید را فراخوانی کرده است.
حالتهای شکست و آنچه مشاهده خواهید کرد
no configuration file provided: not found. ابزار Compose فایلی برای خواندن پیدا نکرد. شما خارج از دایرکتوری پروژه هستید یا COMPOSE_FILE به مسیری اشاره میکند که وجود ندارد. Compose برای یافتن فایل پایه پیشفرض، دایرکتوریهای والد را جستجو میکند، اما برای فایلی که خودتان نامگذاری کردهاید، هیچ جستجویی انجام نمیدهد.
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string. درونیابی (Interpolation) بر اساس فایل .env پروژه و محیط shell انجام میشود و دایرکتوری پروژه در اینجا، همان دایرکتوری اولین فایل -f است. استقرار از دایرکتوری متفاوت با دایرکتوری حاوی .env، این هشدار را به شما میدهد و در نتیجه دیتابیسی خواهید داشت که تمام اتصالات را رد میکند.
ویرایش override شما در docker compose config نمایش داده نمیشود. یا شما فلگ -f را ارسال کردهاید که بارگذاری خودکار override را غیرفعال میکند، یا Compose فایل compose.yaml را در یک دایرکتوری والد پیدا کرده و فایل override شما در کنار آن قرار ندارد. اجرای docker compose config بدون هیچ آرگومان دیگری به شما میگوید که Compose واقعاً در حال ساخت چه مدلی است.
یک bind mount خالی است و Docker دایرکتوریای ایجاد کرده که شما درخواست نکردهاید. مسیر نسبی بر اساس دایرکتوری اولین فایل حل شده است. مسیر را اصلاح کنید، --project-directory را ارسال کنید یا قطعه کد را به پشت include منتقل کنید.
کانتینرها با نامهای جدید بازمیگردند و یک volume خالی به نظر میرسد. نام پروژه تغییر کرده است، زیرا نام پروژه از دایرکتوری اولین فایل پیروی میکند. یک name: در سطح بالا به فایل پایه اضافه کنید تا نامگذاری ثابت بماند. volume قدیمی همچنان با پیشوند قبلی موجود است و docker volume ls آن را نشان خواهد داد.
پورتی که در override حذف کردهاید همچنان باز است. ادغام ports به جای جایگزینی، عمل الحاق (append) را انجام داده است. با docker compose config تأیید کنید، سپس یا از !override استفاده کنید یا ports را از فایل پایه خارج کنید.
FAQ
آیا Compose فایل compose.override.yaml را بهطور خودکار بارگذاری میکند؟
بله، زمانی که docker compose را بدون فلگ -f اجرا میکنید. Compose در دایرکتوری جاری و دایرکتوریهای والد آن به دنبال compose.yaml یا docker-compose.yaml میگردد و اگر فایل override در کنار آن موجود باشد، آن فایل در مرحله دوم بارگذاری میشود. نامهای شناختهشده عبارتند از compose.override.yaml، compose.override.yml، docker-compose.override.yml و docker-compose.override.yaml. ارسال هرگونه -f این قابلیت را غیرفعال میکند، بنابراین docker compose -f compose.yaml up فقط یک فایل را میخواند.
فایلهای چندگانه -f با چه ترتیبی ادغام میشوند؟
از چپ به راست. Compose پیکربندی را به ترتیبی که فایلها را ارائه میدهید میسازد و هر فایل، فایلهای قبلی را بازنویسی کرده یا به آنها اضافه میکند؛ بنابراین آخرین فایل در خط فرمان، در صورت بروز تداخل، اولویت دارد. برای هر دستور در آن پروژه باید از لیست یکسانی استفاده شود که هدف از COMPOSE_FILE=compose.yaml:compose.prod.yaml نیز همین است.
چرا پورت من پس از override کردن همچنان منتشر (publish) میشود؟
زیرا ورودیهای ports توسط کل مجموعه ip، target، published و protocol شناسایی میشوند. یک override از نوع 127.0.0.1:8080:80 در برابر یک پایه 8080:80، در بخش ip تفاوت دارد؛ بنابراین Compose آن را به عنوان پورت دوم در نظر گرفته و هر دو را حفظ میکند. دستور docker compose config را اجرا کنید تا دو ورودی را مشاهده کنید. در نسخه Compose v2.24.4 یا جدیدتر از ports: !override استفاده کنید، یا ports را از فایل پایه حذف کنید تا موردی برای ادغام وجود نداشته باشد.
تفاوت بین include و -f چیست؟
-f چندین فایل را روی یک برنامه لایهبندی میکند و تمام مسیرهای نسبی در هر فایل نسبت به دایرکتوری اولین فایل حل میشوند. include یک برنامه Compose مجزا را فراخوانی میکند و هر مسیرِ include شده، دایرکتوری پروژه مخصوص به خود را حفظ میکند، بنابراین مسیرهای نسبی آن نسبت به خودش حل میشوند. از -f برای لایههای محیطی استک خود و از include برای قطعهای که در جای دیگری نگهداری میشود استفاده کنید. include به نسخه Compose v2.20.0 یا جدیدتر نیاز دارد.
چگونه مقداری را که فایل پایه تنظیم کرده است حذف کنم؟
در نسخه Compose v2.24 یا جدیدتر از تگ !reset استفاده کنید. عبارت ports: !reset [] یا MY_VAR: !reset null را در فایل override بنویسید تا ویژگی به مقدار پیشفرض یا null بازگردد. مقداری که به تگ میدهید الزامی است اما نادیده گرفته میشود. اگر میخواهید به جای پاک کردن یک ویژگی، آن را جایگزین کنید، !override این کار را انجام میدهد و به نسخه v2.24.4 یا جدیدتر نیاز دارد.