SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-28

Docker Compose-এ একাধিক ফাইল কীভাবে merge হয়

compose.override.yaml কখন নিজে থেকে লোড হয়, file order কীভাবে merge বদলায়, ports list কেন port খোলা রাখে এবং dev ও prod আলাদা করতে include কীভাবে ব্যবহার করবেন।

একাধিক ফাইল থাকলে Compose কী করে

Docker Compose একাধিক ফাইল থেকে একটি project তৈরি করতে পারে। এটি ফাইলগুলো পাওয়ার ক্রমে পড়ে এবং সেগুলোকে একটি একক model-এ merge করে। তাই পরের ফাইলে কোনো সাংঘর্ষিক value থাকলে সেটিই কার্যকর হয়। Command line থেকে এটি করার দুটি পদ্ধতি আছে: Compose নিজে থেকে লোড করে এমন override file এবং হাতে দেওয়া -f flag। তৃতীয় পদ্ধতিটি ফাইলের ভেতরেই থাকে, অর্থাৎ include element। এটি অন্য দুটি পদ্ধতি থেকে আলাদাভাবে কাজ করে।

এই merge সাধারণ overwrite নয়। Mapping key অনুযায়ী merge হয়, sequence শেষে যোগ হয়, আর অল্প কিছু field সম্পূর্ণভাবে প্রতিস্থাপিত হয়। এই পার্থক্য থেকেই অপ্রত্যাশিত ফল দেখা দেয়। ports list-টিই প্রায় সবার জন্য সবচেয়ে বেশি সমস্যার কারণ হয়।

নিচের সব আলোচনা Compose v2 ধরে করা হয়েছে। এখানে পুরোনো docker-compose script-এর বদলে docker compose plugin ব্যবহৃত হয়েছে। পরীক্ষা করতে docker compose version চালান। এখনো Compose file না লিখে থাকলে Docker Compose-এর মৌলিক নির্দেশিকা দিয়ে শুরু করে পরে এখানে ফিরে আসুন।

Compose যে override file নিজে থেকে লোড করে

কোনো -f flag ছাড়াই docker compose up চালালে Compose working directory এবং তার parent directory-গুলোতে compose.yaml অথবা docker-compose.yaml খোঁজে। Base file-এর পাশে override file থাকলে Compose সেটিও নিজে থেকেই পরে লোড করে।

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

দুটি file উপস্থিত থাকলে, এটি হাতে দুটিই লিখে দেওয়ার সমতুল্য।

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

Compose যে নামগুলো শনাক্ত করে সেগুলো হলো compose.override.yaml, compose.override.yml এবং পুরোনো docker-compose.override.ymldocker-compose.override.yamlcompose.dev.yaml-এর মতো অন্য কোনো নামের file কেবল -f দিয়ে নির্দিষ্ট করলে লোড হয়।

আপনি একটি -f pass করলেই automatic loading বন্ধ হয়ে যায়। docker compose -f compose.yaml up ঠিক সেই একটি file পড়ে এবং override file উপেক্ষা করে। এই বৈশিষ্ট্যের ওপরই এই guide-এর পরের dev এবং prod pattern তৈরি করা হয়েছে।

সার্ভারে এর প্রভাব দুই দিকেই পড়ে। deploy directory-তে থাকা একটি override file ওই directory থেকে চালানো প্রতিটি bare docker compose command-এ লোড হয়, cron job যে command চালায় সেটিও এর মধ্যে পড়ে। এভাবেই production stack এমন একটি source directory bind-mount করে ফেলে, যেটি কেউ ship করার উদ্দেশ্যে রাখেনি। প্রতিটি deploy-এর পরে docker compose config চালিয়ে এর ফলাফল পড়ুন। deploy unattended হলে, কিছু ভুল হয়েছে—এ কথা কেউ জানালেই কেবল এই check কাজে আসে। এই কাজের জন্য cron job বা systemd OnFailure unit যে push channel-এ post করতে পারে, যেমন একটি self-hosted ntfy server, সেটি ব্যবহার করুন।

-f-এর ক্রম এবং relative path কোথায় resolve হয়

Compose আপনি যে ক্রমে file দেন, সেই ক্রমে configuration তৈরি করে। পরবর্তী file-গুলো আগের file-গুলোর মান override করে এবং নতুন মান যোগ করে। বাম থেকে ডানে গেলে শেষের মান কার্যকর হয়।

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 প্রয়োজন। দুইটি file দিয়ে up এবং একটি file দিয়ে logs চালালে আপনি ভিন্ন merged model-এর সঙ্গে কাজ করছেন। এর ফলে Compose এমন service-এর কথা জানাতে পারে, যা আসলে এই model-এ নেই। One-off command হিসেবে upgrade চালানো stack-এ ঝুঁকি আরও বেশি। যেমন, self-hosted Chatwoot support desk-এর database migration step-এ ভুল file list দিয়ে docker compose run চালালে আপনার service-গুলো যে model ব্যবহার করছে, তার বদলে অন্য একটি model লক্ষ্য করা হয়। File list একবার 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-এ সরাসরি নির্ধারিত যেকোনো মান environment variable-এর মানকে অগ্রাধিকার দেয়।

এখন সেই নিয়মটি দেখুন, যা bind mount নষ্ট করতে পারে। -f দিয়ে একাধিক file ব্যবহার করলে ওই সব file-এর সব relative path প্রথম file-এর directory অনুযায়ী resolve হয়। যে file-এ path লেখা আছে, তার directory অনুযায়ী নয়। deploy/prod/compose.prod.yaml-এর মধ্যে ./data:/var/lib/postgresql/data লিখলেও Compose base file-এর পাশে ./data খোঁজে। এরপর Docker ওই ভুল path-এ একটি empty directory তৈরি করে এবং container-টি তার মধ্যে কোনো data ছাড়াই start হয়। এটি data loss-এর মতো দেখায়, কিন্তু আসলে তা নয়। নিজে base path নির্ধারণ করতে --project-directory দিন। অথবা include ব্যবহার করুন, যা প্রতিটি file-এর path তার নিজস্ব directory অনুযায়ী resolve করে।

Project name-ও একই base directory থেকে আসে। তাই কোন file প্রথমে আছে তা বদলালে project-এর নাম পরিবর্তিত হতে পারে। Project-এর নাম বদলালে নতুন container name এবং নতুন volume name তৈরি হয়। পুরোনো volume-টি পুরোনো নামেই disk-এ থেকে যায়। Base file-এ top-level name: দিয়ে নামটি নির্দিষ্ট করে রাখুন।

name: myapp

কোন ক্ষেত্রগুলো একত্রিত হয় এবং কোনগুলো প্রতিস্থাপিত হয়

Compose ক্ষেত্রের নাম অনুযায়ী নয়, মানের ধরন অনুযায়ী merge করে।

  • একক-মূল্যের ক্ষেত্র প্রতিস্থাপিত হয়। image, command, entrypoint এবং mem_limit সরাসরি পরের মান গ্রহণ করে। কোনো command-এ একটি argument যোগ করা যায় না, কারণ override পুরো লাইনটি নতুন করে লিখে দেয়।
  • Mapping key অনুযায়ী merge হয়। environment, labels, volumes এবং devices উভয় ফাইলের প্রতিটি key ধরে রাখে। উভয় ফাইলে একই key থাকলে পরের ফাইলের মান কার্যকর হয়। environment এবং labels-এর ক্ষেত্রে key হলো variable বা label-এর নাম। volumes এবং devices-এর ক্ষেত্রে key হলো container path।
  • Sequence একত্রে যোগ হয়। dns, dns_search, expose, tmpfs এবং external_links পরপর যুক্ত হয়। expose: ["3000"] থাকা একটি base-এর সঙ্গে ["4000", "5000"] থাকা একটি override merge করলে ["3000", "4000", "5000"] তৈরি হয়।

চারটি sequence-এ identity key থাকে। তাই একই key-র entry append না হয়ে merge হয়। volumes, secrets এবং configs target অনুযায়ী মিলে যায়। ports ip, target, published এবং protocol-এর সমন্বয় অনুযায়ী মিলে যায়।

ports নিয়মটি দুবার পড়ুন, কারণ এখানেই ভুল হওয়ার সম্ভাবনা বেশি। দুটি port entry তখনই একই entry হিসেবে গণ্য হয়, যখন ওই চারটি অংশের সবগুলো মিলে যায়। যেকোনো একটি অংশ পরিবর্তন করলে Compose এটিকে দ্বিতীয়, সম্পর্কহীন port হিসেবে দেখে। তাই উভয় entry-ই রাখা হয়।

override প্রয়োগের পরও আপনার port কেন published থাকে

একটি base file প্রতিটি interface-এ service publish করে:

services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"

একটি override service-টিকে শুধু localhost-এ bind করার জন্য লেখা হয়েছে, কারণ এর সামনে একটি reverse proxy থাকবে:

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

এটি কাজ করেছে ধরে নেওয়ার আগে ফলাফল পরীক্ষা করুন।

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

Output-এ উভয় entry-ই রয়েছে। ip অংশটি আলাদা; 0.0.0.0 এবং 127.0.0.1 এক নয়। তাই merge-এর দৃষ্টিতে এগুলো দুটি আলাদা port, এবং আপনি যে public binding সরানোর চেষ্টা করেছিলেন সেটি এখনও model-এ রয়েছে। Docker-এর ক্ষেত্রে এটি আরও গুরুত্বপূর্ণ, কারণ published port আপনার firewall rule-এর আগেই iptables-এ লেখা হয়। এই প্রক্রিয়াটি published Docker port কীভাবে ufw অতিক্রম করে-এ ব্যাখ্যা করা হয়েছে।

এর দুটি সমাধান আছে। সরাসরি সমাধান হলো !override tag ব্যবহার করা। এটি সম্পূর্ণ attribute প্রতিস্থাপন করে এবং merge rules এড়িয়ে যায়:

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

!override ব্যবহারের জন্য Compose v2.24.4 বা তার পরের সংস্করণ প্রয়োজন। Portable সমাধানে কোনো tag দরকার নেই: base file থেকে ports সম্পূর্ণ বাদ দিন এবং এটি শুধু environment-specific file-গুলোতে declare করুন। Merge করার মতো কিছু না থাকলে অনিচ্ছাকৃতভাবে প্রকাশ পাওয়ারও কিছু থাকে না। নিচের worked example-এ এই pattern-ই ব্যবহার করা হয়েছে।

ভিত্তি ফাইলে নির্ধারিত কোনো মান মুছে ফেলা

!reset কোনো attribute সরিয়ে দেয় এবং সেটিকে default মানে বা null-এ ফিরিয়ে দেয়। এটি একটি মান গ্রহণ করে কিন্তু তা উপেক্ষা করে। তাই বৈধ এবং খালি কোনো মান লিখুন।

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

!reset-এর জন্য Compose v2.24 বা নতুন সংস্করণ প্রয়োজন। ভিত্তি ফাইলটি আপনার সম্পাদনার জন্য না হলে এটি ব্যবহার করুন, যেমন কোনো vendor fragment যা আপনি অন্তর্ভুক্ত করেন। প্রকাশিত upstream stack এর সঠিক উদাহরণ: self-hosted AFFiNE workspace-এর পেছনের Compose file-এ আপনার লেখা নয় এমন চারটি container ঘোষণা করা আছে। !reset ব্যবহার করে file-টি fork না করেই এবং সেটি অনুসরণ করার দায়িত্ব না নিয়েই ওই container-গুলোর একটির একটি attribute মুছে দিতে পারবেন।

অংশ থেকে stack তৈরি করার জন্য include

include আপনার model-এ আরেকটি Compose application যুক্ত করে। এটি top-level element, flag নয়।

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

include-এর প্রতিটি path নিজস্ব project directory-সহ আলাদা Compose application model হিসেবে load হয়। তাই ওই ফাইলের ভেতরের relative path সেই ফাইলের নিজস্ব directory অনুযায়ী resolve হয়। এটিই -f-এর সঙ্গে প্রকৃত পার্থক্য। অন্য folder বা অন্য repository-তে থাকা fragment-এর জন্য include উপযুক্ত হওয়ার কারণও এটি। আপনি নিজে লেখেননি—এমন vendor stack সাধারণত এভাবেই সাজানো থাকে। যেমন, self-hosted Authentik SSO install-এর পেছনে থাকা multi-service Compose file নিজস্ব directory-তে নিজস্ব relative path অক্ষুণ্ণ রেখে থাকতে পারে। আপনার file তখন শুধু আপনার নিজের service-গুলো নিয়ে থাকে।

Long form-এ sub-option ব্যবহার করা যায়।

include:
  - path:
      - ../monitoring/compose.yaml
      - ../monitoring/compose.vps.yaml
    project_directory: ../monitoring
    env_file: ../monitoring/.env

path একটি list গ্রহণ করে। ফলাফল আপনার model-এ যুক্ত হওয়ার আগে ওই file-গুলো স্বাভাবিক নিয়মে একে অপরের সঙ্গে merge হয়। project_directory included file-এ relative path resolve করার জন্য ব্যবহৃত base path নির্ধারণ করে। env_file included file-কে interpolation-এর জন্য নিজস্ব variable দেয়। ফলে shared fragment নীরবে আপনার project-এর .env পড়ে না। include ব্যবহারের জন্য Compose v2.20.0 বা পরবর্তী সংস্করণ প্রয়োজন। আপনি ইতিমধ্যে চালু থাকা stack-এ একটি single-container add-on যুক্ত করলেও একই option ব্যবহার করতে পারেন। যেমন Halcyon, যা Jellyfin library-কে 90s rental store-এর মতো দেখায়। এর file-এ নিজস্ব image tag এবং নিজস্ব env_file থাকে। তাই এটি upgrade করতে আপনার media stack-এর file পরিবর্তন করতে হয় না।

আপনার file এবং included file-এ একই resource name থাকলে সেগুলো নীরবে merge না করে error হিসেবে জানানো হয়। এটি ইচ্ছাকৃত আচরণ। Included file-এ ঘোষিত কোনো কিছু পরিবর্তন করতে হলে পরিবর্তনটি compose.override.yaml-এ রাখুন। Override assembled model-এ প্রয়োগ হয়। তাই resource-এর সঙ্গে সংঘর্ষ না ঘটিয়ে included resource পরিবর্তন করা যায়। Upstream file প্রতিটি release-এ নতুন করে লেখা হয়—এমন stack-এর ক্ষেত্রে এই অভ্যাস বিশেষভাবে কার্যকর। উদাহরণ হিসেবে PhotoPrism বনাম Immich-এ আলোচিত multi-container photo server-গুলোর কথা বলা যায়। সেখানে localhost binding বা অতিরিক্ত volume আপনার override-এ রাখা উচিত, কারণ পরবর্তী upgrade-এ upstream file প্রতিস্থাপিত হবে।

সংক্ষেপে: include আলাদা application একত্র করে, আর -f একটি application-এর ওপর configuration layer যোগ করে।

একটি VPS-এ dev এবং prod আলাদা রাখা

তিনটি ফাইলে পুরো প্যাটার্নটি দেখানো হলো। base file-এ সর্বত্র প্রযোজ্য বিষয়গুলো ঘোষণা করা হয়, এবং এতে কোনো 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 condition-এর কারণে app শুধু এমন database-এর জন্য অপেক্ষা করে, যেটি উত্তর দিচ্ছে; শুধু বিদ্যমান এমন container-এর জন্য নয়। এটি healthcheck এবং depends_on condition-এ ব্যাখ্যা করা হয়েছে। POSTGRES_PASSWORD project-এর .env file থেকে interpolate করা হয়। এই file কখনো git-এ রাখা হয় না। নিরাপদ বিকল্পের জন্য env file এবং Compose secret দেখুন।

এরপর আছে compose.override.yaml, যা Compose নিজে থেকেই load করে। এটি developer-এর file।

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 চালালে এই দুই file merge হয়। command image-এর default-কে প্রতিস্থাপন করে, কারণ এটি single-valued। LOG_LEVEL, info-কে প্রতিস্থাপন করে, কারণ environment key অনুযায়ী merge হয়। bind mount এবং প্রকাশিত দুইটি port সম্পূর্ণ নতুন সংযোজন। database port-টি localhost-এ bind করা হয়েছে, যাতে shared network-এ থাকা অন্য কোনো laptop PostgreSQL-এ room-এ প্রবেশের সুযোগ না পায়।

সবশেষে compose.prod.yaml। এর নাম এমন নয়, যা Compose খুঁজে দেখে। তাই এটি ভুল করে load হয় না।

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

VPS-এ দুইটি file-এর নাম উল্লেখ করুন। এই নাম উল্লেখ করাই override file বাদ দেওয়ার সঠিক পদ্ধতি।

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-এ দুইটি service-ই running হিসেবে দেখা উচিত, এবং db-এ (healthy) দেখা উচিত। আপনি -f ব্যবহার করেছেন বলে compose.override.yaml পড়া হয়নি। তাই file-টি একই directory-তে থাকলেও dev command, source bind mount এবং public port 3000 production-এ পৌঁছাতে পারে না। Port 8000 শুধু localhost-এ চালু আছে, proxy-এর জন্য প্রস্তুত। দ্বিতীয় service যোগ করার সময় Traefik-এর পেছনে একাধিক app চালানো দেখুন।

server-এর .env-এ COMPOSE_FILE=compose.yaml:compose.prod.yaml সেট করুন। এরপর আপনার বাকি command-গুলো আবার সরাসরি docker compose logs -f app হয়ে যাবে।

একটি single-service stack-ও একই কাঠামো অনুসরণ করে। কারণ self-hosted openGym workout tracker-কে প্রথম passkey enrol করার আগে proxy-এর পেছনে TLS-এর মাধ্যমে উত্তর দিতে হয়। base file-এ কোনো ports না থাকলেই কোনো ভুল public binding proxy-এর আগে request নেওয়ার সুযোগ পায় না।

Deploy করার আগে merged model পড়ুন

docker compose config সম্পূর্ণ merged এবং interpolated model প্রিন্ট করে। এটি কোনো preview নয়। Compose যে নির্দিষ্ট input-এর ওপর কাজ করবে, এটিই সেই input। তাই 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 name তালিকাভুক্ত করে। এর মাধ্যমে দ্রুত নিশ্চিত করা যায় যে কোনো include প্রত্যাশিত জিনিস pull করেছে কি না।

ব্যর্থতার ধরন এবং আপনি যা দেখতে পাবেন

no configuration file provided: not found. Compose পড়ার জন্য কিছুই খুঁজে পায়নি। আপনি project directory-এর বাইরে আছেন, অথবা COMPOSE_FILE এমন একটি path নির্দেশ করছে, যার অস্তিত্ব নেই। Compose default base file খুঁজতে parent directory-গুলো পরীক্ষা করে, কিন্তু আপনি নিজে নির্দিষ্ট করা 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-এর পরে সরিয়ে নিন।

Container-গুলো নতুন name নিয়ে ফিরে এসেছে এবং একটি volume খালি দেখাচ্ছে। Project name পরিবর্তিত হয়েছে, কারণ project name প্রথম file-এর directory অনুসরণ করে। Base file-এ top-level name: যোগ করুন। এতে name আর পরিবর্তিত হবে না। পুরোনো volume-টি পুরোনো prefix-এর অধীনে এখনও আছে। docker volume ls চালালে এটি দেখা যাবে।

Override-এ সরিয়ে দেওয়া একটি port এখনও open। ports merge replace না করে append করেছে। docker compose config দিয়ে নিশ্চিত করুন। এরপর হয় !override ব্যবহার করুন, নয়তো ports base file-এর বাইরে সরিয়ে নিন।

FAQ

Compose কি স্বয়ংক্রিয়ভাবে compose.override.yaml লোড করে?

হ্যাঁ, যখন আপনি কোনো -f flag ছাড়া docker compose চালান। Compose working directory এবং তার parent directory-গুলোতে compose.yaml বা docker-compose.yaml খোঁজে। একই directory-তে override file থাকলে সেটি দ্বিতীয় ধাপে লোড হয়। স্বীকৃত নাম হলো compose.override.yaml, compose.override.yml, docker-compose.override.yml এবং docker-compose.override.yaml। যেকোনো -f দিলে এই আচরণ বন্ধ হয়। তাই docker compose -f compose.yaml up কেবল একটি file পড়ে।

একাধিক -f file কোন ক্রমে merge হয়?

বাম থেকে ডানে। আপনি যে ক্রমে file-গুলো দেন, Compose সেই ক্রমে configuration তৈরি করে। প্রতিটি file তার আগের file-গুলোর মান override ও add করে। তাই একই conflict থাকলে command line-এর শেষ file-এর মান কার্যকর হয়। ওই project-এর প্রতিটি command-এ একই তালিকা ব্যবহার করতে হবে। এই কাজের জন্য COMPOSE_FILE=compose.yaml:compose.prod.yaml ব্যবহৃত হয়।

override করার পরও আমার port কেন published থাকে?

কারণ ports entry-গুলো ip, target, published এবং protocol-এর সম্পূর্ণ সমষ্টি দিয়ে শনাক্ত হয়। 8080:80 base-এর বিপরীতে 127.0.0.1:8080:80 override করলে ip অংশে পার্থক্য থাকে। তাই Compose এটিকে দ্বিতীয় port হিসেবে ধরে এবং উভয়টি রেখে দেয়। docker compose config চালালে আপনি দুটি entry দেখতে পাবেন। Compose v2.24.4 বা পরবর্তী সংস্করণে ports: !override ব্যবহার করুন। অথবা base file-এ ports রাখবেন না, যাতে merge করার মতো কোনো মান না থাকে।

include এবং -f-এর মধ্যে পার্থক্য কী?

-f একাধিক file একটি application-এর ওপর layer করে। প্রতিটি file-এর relative path প্রথম file-এর directory ধরে resolve হয়। include একটি আলাদা Compose application অন্তর্ভুক্ত করে। প্রতিটি included path তার নিজস্ব project directory বজায় রাখে, তাই তার relative path নিজস্ব directory ধরে resolve হয়। নিজের stack-এর environment layer-এর জন্য -f ব্যবহার করুন। অন্যত্র রক্ষণাবেক্ষণ করা fragment-এর জন্য include ব্যবহার করুন। include-এর জন্য Compose v2.20.0 বা পরবর্তী সংস্করণ প্রয়োজন।

Base file-এ সেট করা কোনো মান কীভাবে সরাব?

Compose v2.24 বা পরবর্তী সংস্করণে !reset tag ব্যবহার করুন। overriding file-এ ports: !reset [] বা MY_VAR: !reset null লিখলে attribute-টি default মানে বা null-এ ফিরে যায়। Tag-এ দেওয়া মান প্রয়োজনীয়, কিন্তু তা উপেক্ষা করা হয়। Attribute মুছে না দিয়ে প্রতিস্থাপন করতে চাইলে !override ব্যবহার করুন। এর জন্য v2.24.4 বা পরবর্তী সংস্করণ প্রয়োজন।