Docker Compose নেটওয়ার্কিং কীভাবে কাজ করে?
Docker Compose ডিফল্ট ব্রিজ নেটওয়ার্ক, সার্ভিস নেম ডিএনএস এবং হোস্ট মোড ব্যবহারের সঠিক নিয়ম জানুন। প্রজেক্টের মধ্যে নেটওয়ার্ক শেয়ারিং এবং UFW বাইপাস করা পোর্ট নিয়ে বিস্তারিত আলোচনা।
আপনার অ্যাপ শুরু হওয়ার আগে Compose যা তৈরি করে
Docker Compose নেটওয়ার্কিং একটি নিয়ম দিয়ে শুরু হয়: docker compose up প্রজেক্টের জন্য একটি প্রাইভেট নেটওয়ার্ক তৈরি করে, প্রতিটি সার্ভিসকে এর সাথে যুক্ত করে এবং সার্ভিসগুলোকে তাদের নাম ব্যবহার করে একে অপরের সাথে যোগাযোগ করতে দেয়। এটি পাওয়ার জন্য আপনাকে একটিও networks: লাইন লিখতে হয় না। Compose নেটওয়ার্কিং নিয়ে অধিকাংশ বিভ্রান্তি তৈরি হয় এই ডিফল্ট বিষয়টি জানা না থাকার কারণে।
নিচে একটি ছোট ফাইল দেওয়া হলো। এটিকে shop নামের একটি ডিরেক্টরিতে compose.yaml নামে সেভ করুন।
services:
web:
image: nginx:1.27
ports:
- "8080:80"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: exampleএটিকে চালু করুন এবং Docker কী তৈরি করেছে তা দেখুন:
docker compose up -d
docker network lsতালিকায় এখন shop_default নামের একটি নেটওয়ার্ক রয়েছে। Compose এর নাম দেয় <project>_default এবং প্রজেক্টের নাম ডিফল্টভাবে ডিরেক্টরির ছোট হাতের নাম হিসেবে সেট হয়। এটিকে docker compose -p myproject up -d অথবা ফাইলের টপ-লেভেলে name: myproject ব্যবহার করে পরিবর্তন করা যায়। এর ড্রাইভার হলো bridge, যা হোস্টের ভেতরে একটি ভার্চুয়াল সুইচ হিসেবে কাজ করে। প্রতিটি কন্টেইনার একটি প্রাইভেট সাবনেটে একটি অ্যাড্রেস পায় এবং আউটবাউন্ড ট্রাফিক হোস্টের বাইরে যাওয়ার সময় হোস্টের অ্যাড্রেসে রূপান্তরিত হয়।
docker compose down নেটওয়ার্কটিকে পুনরায় মুছে ফেলে। এই কারণেই একটি পুরনো প্রজেক্টের অব্যবহৃত কন্টেইনার একটি নেটওয়ার্ককে চালু রাখতে পারে: Docker তখন error while removing network: network shop_default has active endpoints এর মাধ্যমে ত্রুটি দেখায় এবং এর সমাধান হলো নেটওয়ার্কের সাথে যুক্ত কন্টেইনারটিকে থামানো বা মুছে ফেলা।
আপনি যদি Compose-এ নতুন হন, তবে Compose ফাইলের গঠন এবং লাইফসাইকেল কমান্ড আগে পড়ে নেওয়া ভালো, কারণ নিচের সবকিছুই ধরে নেয় যে আপনি একটি প্রজেক্ট শুরু এবং বন্ধ করতে পারেন।
সার্ভিস নেম অনুযায়ী DNS হলো সেই অংশ যা নতুনরা এড়িয়ে যায়
যেকোনো ইউজার-ডিফাইনড নেটওয়ার্কে, Docker একটি এমবেডেড DNS সার্ভার চালায় যা প্রতিটি কন্টেইনার 127.0.0.11-এ দেখতে পায়। এটি সার্ভিস নেমগুলোকে বর্তমান কন্টেইনার অ্যাড্রেসে রিজলভ করে। তাই web কোনো কনফিগারেশন ছাড়াই 5432 পোর্টে db হোস্টনামে ডাটাবেসে পৌঁছাতে পারে।
docker compose exec web getent hosts dbএটি 172.18.0.2 db-এর মতো একটি লাইন প্রিন্ট করে। যদি এটি কিছুই প্রিন্ট না করে, তবে দুটি সার্ভিস একই নেটওয়ার্কে নেই।
যে ভুলটি প্রায় সবাই একবার করে তা হলো অ্যাপ্লিকেশন কনফিগে localhost ব্যবহার করা। একটি কন্টেইনারের ভেতরে, localhost হলো সেই কন্টেইনারটি, হোস্ট বা অন্য কোনো সার্ভিস নয়। Postgres ক্লায়েন্টরা এটি স্পষ্টভাবে রিপোর্ট করে:
could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP connections on port 5432?কানেকশন স্ট্রিংটি হওয়া উচিত postgresql://postgres:example@db:5432/postgres। হোস্ট অংশটি হলো সার্ভিস নেম।
দুটি বিষয় যা পরবর্তীতে সময় বাঁচাবে। নামগুলো বর্তমানে যা চলছে তার ওপর ভিত্তি করে রিজলভ হয়, তাই docker compose up -d --scale web=3 তিনটি অ্যাড্রেসসহ একটি নাম দেয়, এবং যে ক্লায়েন্ট চিরস্থায়ীভাবে DNS ক্যাশ করে রাখে তা নিজেকে একটি মৃত কন্টেইনারের সাথে আটকে ফেলবে। আর সাধারণ docker run (যাতে কোনো --network নেই) দ্বারা ব্যবহৃত লিগ্যাসি bridge নেটওয়ার্কে কোনো নেম রিজল্যুশন নেই, যে কারণে 2016 সালের কন্টেইনার লিঙ্ক বিষয়ক পরামর্শগুলো আপনার বর্তমান অভিজ্ঞতার সাথে মেলে না।
দুটি সার্ভিস সংযুক্ত করতে আপনার ports:-এর প্রয়োজন নেই
ports: হোস্ট মেশিনে একটি কন্টেইনার পোর্ট উন্মুক্ত করে। এটি Docker-এর বাইরের ট্র্যাফিকের জন্য ব্যবহৃত হয়। সার্ভিস-টু-সার্ভিস ট্র্যাফিকের সাথে এর কোনো সম্পর্ক নেই, যা প্রজেক্ট নেটওয়ার্কের পুরো পোর্ট রেঞ্জ জুড়ে এমনিতেই কাজ করে।
তাই অনেক মানুষ তাদের ডাটাবেস সার্ভিসে যে ports: - "5432:5432" যোগ করেন, তা কোনো উপকারে আসে না বরং ক্ষতি করে: এটি সার্ভারের পাবলিক ইন্টারফেসে Postgres-কে উন্মুক্ত করে দেয়। এটি মুছে ফেলুন। যদি মাইগ্রেশনের জন্য আপনার ল্যাপটপ থেকে এটি অ্যাক্সেস করার প্রয়োজন হয়, তবে "127.0.0.1:5432:5432" ব্যবহার করে এটিকে লুপব্যাক (loopback) ইন্টারফেসে বাইন্ড করুন এবং একটি SSH টানেলের মাধ্যমে সংযোগ স্থাপন করুন। লিসেনিং সকেট, পাবলিশড পোর্ট এবং ফায়ারওয়াল রুলের মধ্যে পার্থক্য Linux-এ পোর্ট এবং লিসেনিং সার্ভিস কীভাবে কাজ করে অংশে আলোচনা করা হয়েছে।
Compose-এর ক্ষেত্রে expose: শুধুমাত্র ডকুমেন্টেশনের জন্য ব্যবহৃত হয়। এটি কোনো পোর্ট খোলে না, কারণ একই নেটওয়ার্কের কন্টেইনারগুলোর মধ্যে কোনো পোর্ট বন্ধ থাকে না।
কখন network_mode host ব্যবহার করা সঠিক এবং এর প্রভাব কী
Host মোড কন্টেইনারের নিজস্ব নেটওয়ার্ক নেমস্পেস বাদ দেয় এবং প্রসেসটিকে সরাসরি হোস্টের ইন্টারফেসগুলো ব্যবহারের সুযোগ দেয়।
services:
probe:
image: alpine:3.20
network_mode: host
command: sleep infinityএটি ব্যবহারের পেছনে বাস্তবসম্মত কারণ রয়েছে। যে প্রসেসগুলোর স্থানীয় নেটওয়ার্কে ব্রডকাস্ট বা মাল্টিকাস্ট ট্রাফিক দেখার প্রয়োজন হয়, যেমন মিডিয়া সার্ভার বা হোম অটোমেশন হাবের জন্য ডিভাইস ডিসকভারি, সেগুলো ব্রিজের পেছন থেকে তা দেখতে পায় না। কারণ ব্রিজ সেই ট্রাফিক কন্টেইনারে ফরোয়ার্ড করে না। একটি মনিটরিং এজেন্ট যা হোস্টের ইন্টারফেস কাউন্টার পড়ে, তার হোস্টের ইন্টারফেসগুলো প্রয়োজন হয়। এছাড়া, এতে অ্যাড্রেস ট্রান্সলেশন ধাপটি এড়িয়ে যাওয়া যায়, যা উচ্চ প্যাকেট রেটের ক্ষেত্রে গুরুত্বপূর্ণ।
এর প্রভাবগুলো সুনির্দিষ্ট।
ports: কাজ করা বন্ধ করে দেয়। Docker সতর্ক করে যে, host নেটওয়ার্ক মোড ব্যবহার করলে পাবলিশ করা পোর্টগুলো বাতিল হয়ে যায় এবং কন্টেইনারটি তার প্রসেস যা বাইন্ড করে, তা-ই ব্যবহার করে। দুটি host মোড কন্টেইনার যদি একই পোর্ট 8080 ব্যবহার করতে চায়, তবে সংঘর্ষ ঘটে এবং দ্বিতীয়টি bind: address already in use এর কারণে বন্ধ হয়ে যায়।
সার্ভিস নামের মাধ্যমে নেম রেজোলিউশন উভয় দিক থেকেই কাজ করে না। কন্টেইনারটি প্রজেক্ট নেটওয়ার্কে থাকে না, তাই এটি db রেজলভ করতে পারে না এবং অন্যান্য সার্ভিসগুলোও একে রেজলভ করতে পারে না। এটি কেবল হোস্টের পাবলিশ করা পোর্টের মাধ্যমেই তাদের সাথে যোগাযোগ করতে পারে, যা সাধারণত 127.0.0.1 এ থাকে।
আইসোলেশন বা বিচ্ছিন্নতা আর থাকে না। একটি host মোড কন্টেইনারের ভেতরে যে প্রসেস 0.0.0.0 বাইন্ড করে, তা আপনার সার্ভারের প্রতিটি ইন্টারফেসে লিসেন করে, যার মধ্যে পাবলিক ইন্টারফেসটিও অন্তর্ভুক্ত, ঠিক যেমন apt দিয়ে ইনস্টল করা কোনো প্যাকেজ করে। এর একটি ইতিবাচক দিক হলো: এই ট্রাফিক স্বাভাবিক ইনপুট পাথ অনুসরণ করে, তাই UFW রুলগুলো এর ওপর কার্যকর হয়, যা পাবলিশ করা পোর্টের ক্ষেত্রে সত্য নয়।
Host মোড একটি Linux Docker Engine ফিচার। Docker Desktop এটি কেবল 4.34 সংস্করণ থেকে সমর্থন করে এবং তা সক্রিয় করার পরেই কাজ করে। এর অতিরিক্ত সীমাবদ্ধতা হলো, কন্টেইনারগুলো হোস্টের IP অ্যাড্রেস বাইন্ড করতে পারে না এবং কেবল TCP ও UDP হ্যান্ডেল করা হয়। যদি আপনার টিমের অর্ধেক সদস্য Linux সার্ভারে এবং অর্ধেক Docker Desktop-এ কাজ করেন, তবে একই ফাইল ভিন্নভাবে কাজ করবে বলে আশা করতে পারেন।
যখন আপনার হোস্টের ইন্টারফেসগুলো প্রয়োজন হবে, তখনই host মোড ব্যবহার করুন। সংযোগের সমস্যা সমাধানের জন্য এটি ব্যবহার করবেন না, কারণ এটি সাধারণত একটি সমস্যার পরিবর্তে আরও কঠিন সমস্যা তৈরি করে।
দুটি Compose প্রজেক্টকে একটি এক্সটারনাল নেটওয়ার্কের মাধ্যমে সংযুক্ত করা
একটি প্রজেক্টের তৈরি করা নেটওয়ার্ক অন্য প্রজেক্টের কাছে দৃশ্যমান হয় না। এই কারণেই proxy/compose.yaml-এ থাকা একটি রিভার্স প্রক্সি একই সার্ভারে থাকা সত্ত্বেও app/compose.yaml-এর কোনো অ্যাপ দেখতে পায় না। এর সমাধান হলো এমন একটি নেটওয়ার্ক তৈরি করা যার মালিকানা কোনো প্রজেক্টেরই নয়।
এটি একবার হাতে তৈরি করুন:
docker network create edgeএরপর প্রতিটি প্রজেক্টে এটিকে এক্সটারনাল হিসেবে ঘোষণা করুন। প্রক্সি সাইডে:
services:
proxy:
image: traefik:v3.1
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- edge
networks:
edge:
name: edge
external: trueঅ্যাপ্লিকেশন সাইডে:
services:
app:
image: nginx:1.27
networks:
- edge
- internal
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: example
networks:
- internal
networks:
edge:
name: edge
external: true
internal:external: true কমান্ডটি Compose-কে নির্দেশ দেয় নতুন নেটওয়ার্ক তৈরি না করে বিদ্যমান নেটওয়ার্কের সাথে যুক্ত হতে এবং docker compose down করার সময় সেটিকে অপরিবর্তিত রাখতে। আলাদা name: কি (key) যতটা মনে হয় তার চেয়েও বেশি গুরুত্বপূর্ণ: এটি ছাড়া Compose হুবহু edge নামের একটি নেটওয়ার্ক খোঁজে, আর এটি থাকলে আপনি আপনার ফাইলে নেটওয়ার্কটিকে এক নামে এবং হোস্ট মেশিনে অন্য নামে ডাকতে পারেন।
যদি নেটওয়ার্কটি বিদ্যমান না থাকে, তবে Compose চালু হতে অস্বীকার করবে এবং জানাবে যে নেটওয়ার্কটি এক্সটারনাল হিসেবে ঘোষণা করা হয়েছে কিন্তু খুঁজে পাওয়া যায়নি। তাই আগে এটি তৈরি করুন।
অ্যাপ্লিকেশন ফাইলটি internal দিয়ে কী করছে তা লক্ষ্য করুন। ডাটাবেসটি শুধুমাত্র সেই প্রজেক্ট-লোকাল নেটওয়ার্কে থাকে, তাই প্রক্সি সেটিতে পৌঁছাতে পারে না এবং শুধুমাত্র app তা করতে পারে। একটি নেটওয়ার্কের অধীনে internal: true যোগ করলে তা আরও এক ধাপ এগিয়ে বাইরের জগতের সাথে এর রাউট সম্পূর্ণভাবে মুছে ফেলে। ডাটাবেসের জন্য এটি একটি ভালো ডিফল্ট সেটিংস, তবে এটি সেট করার আগে একটি বিষয় জেনে রাখা জরুরি: ইন্টারনাল নেটওয়ার্কে থাকা কোনো কন্টেইনার বাইরের কিছু ডাউনলোড করতে পারে না, তাই স্টার্টআপের সময় যে এন্ট্রি পয়েন্ট apt-get update বা pip install চালায়, তা হ্যাং হয়ে যাবে এবং টাইমআউট এরর দেখাবে।
রাউটিং রুল এবং সার্টিফিকেটসহ সম্পূর্ণ সেটআপের জন্য দেখুন একটি Traefik ইনস্ট্যান্সের পেছনে একাধিক অ্যাপ চালানো।
প্রকাশিত পোর্টগুলো UFW বাইপাস করে
এটি Compose নেটওয়ার্কিংয়ের সেই অংশ যা একটি নিরাপত্তা ঝুঁকির কারণ হয়ে দাঁড়ায়। আপনি একটি পোর্ট প্রকাশ (publish) করেন, আপনি নিশ্চিত করেন যে UFW সক্রিয় আছে এবং SSH ছাড়া সবকিছু ব্লক করে রেখেছে, তবুও সার্ভিসটি ইন্টারনেট থেকে অ্যাক্সেস করা যায়।
sudo ufw status
curl http://203.0.113.10:8080UFW বলে যে পোর্টটি ব্লক করা আছে। এরপরও curl পেজটি রিটার্ন করে। এখানে কোনো কিছু নষ্ট হয়নি। Docker সরাসরি iptables-এ নিজস্ব অ্যাড্রেস ট্রান্সলেশন এবং ফরওয়ার্ডিং রুল লিখে ফেলে। ফলে প্রকাশিত কন্টেইনার পোর্টের ট্রাফিক হোস্টের কাছে পৌঁছানোর পরিবর্তে সরাসরি কন্টেইনারে ফরওয়ার্ড হয়ে যায়। তাই এটি স্থানীয় ট্রাফিকের জন্য UFW-এর ম্যানেজ করা চেইন অতিক্রম করে না। এছাড়া, Docker-এর রুলগুলো UFW-এর রুলের আগেই ম্যাচ করা হয়।
এর সংক্ষিপ্ত সমাধান হলো, শুধুমাত্র যেখানে প্রয়োজন সেখানে পোর্ট প্রকাশ করা:
ports:
- "127.0.0.1:8080:80"এটি হোস্ট সাইডকে লুপব্যাক (loopback)-এর সাথে বাইন্ড করে। ফলে পোর্টটি শুধুমাত্র সার্ভার থেকে এবং SSH টানেলের মাধ্যমে অ্যাক্সেস করা যায়, অন্য কোথাও থেকে নয়। পাবলিক এন্ট্রি পয়েন্টটিকে একটি রিভার্স প্রক্সির পেছনে রাখুন, যা ইচ্ছাকৃতভাবে 80 এবং 443 পোর্ট প্রকাশ করে। পূর্ণাঙ্গ ব্যাখ্যা, যার মধ্যে DOCKER-USER চেইন অন্তর্ভুক্ত রয়েছে (যেসব ক্ষেত্রে আপনাকে প্রকাশিত পোর্ট ফিল্টার করতে হবে), তা কেন Docker UFW বাইপাস করে পোর্ট প্রকাশ করে এবং কীভাবে তা ঠিক করবেন-এ দেওয়া আছে।
চারটি কমান্ডের মাধ্যমে ডিবাগ করার পদ্ধতি
প্রথমে প্রতিটি কন্টেইনার আসলে কোন নেটওয়ার্কে আছে তা যাচাই করুন:
docker network inspect shop_defaultContainers ব্লকটি প্রতিটি সংযুক্ত কন্টেইনার এবং তাদের ঠিকানা তালিকাভুক্ত করে। কোনো সার্ভিস যদি সেই তালিকায় না থাকে, তবে সেটি অন্য কোনো নেটওয়ার্কে আছে, হোস্ট মোডে আছে, অথবা চলছে না।
একই নেটওয়ার্কে সংযুক্ত একটি অস্থায়ী কন্টেইনার থেকে নেম রেজোলিউশন পরীক্ষা করুন, যাতে আপনার নিজস্ব ইমেজের ভেতরে কোনো টুলিংয়ের প্রয়োজন না হয়:
docker run --rm --network shop_default busybox nslookup db
docker run --rm --network shop_default busybox nc -zv db 5432nslookup ব্যর্থ হওয়া মানে নেম রেজোলিউশন বা নেটওয়ার্ক মেম্বারশিপে সমস্যা আছে। nslookup সফল হওয়া অথচ nc ব্যর্থ হওয়ার অর্থ হলো সার্ভিসটি চলছে কিন্তু সেই পোর্টে লিসেন করছে না, অথবা সেটি 0.0.0.0 এর পরিবর্তে তার নিজস্ব কন্টেইনারের ভেতরে 127.0.0.1 তে লিসেন করছে। ডেভেলপমেন্ট সার্ভারের ক্ষেত্রে এটি সচরাচর ঘটে এবং এর সমাধান Docker-এ নয়, বরং অ্যাপ্লিকেশনের বাইন্ড অ্যাড্রেসে রয়েছে।
আরেকটি ব্যর্থতা যা Docker বাগ বলে মনে হতে পারে। যদি কন্টেইনারগুলো একে অপরের সাথে যোগাযোগ করতে পারে কিন্তু আপনার অফিস বা VPN নেটওয়ার্কের কোনো মেশিনে পৌঁছাতে না পারে, তবে সম্ভবত Docker সাবনেট সেই নেটওয়ার্কের সাথে ওভারল্যাপ করছে। Docker ডিফল্টভাবে 172.17.0.0/16 থেকে উপরের দিকে অ্যাড্রেস বরাদ্দ করে। /etc/docker/daemon.json-এ পুলটি পরিবর্তন করুন:
{
"default-address-pools": [
{ "base": "10.200.0.0/16", "size": 24 }
]
}এরপর sudo systemctl restart docker কমান্ডটি চালান এবং প্রভাবিত নেটওয়ার্কগুলো পুনরায় তৈরি করুন, কারণ একটি বিদ্যমান নেটওয়ার্ক তার তৈরির সময়কার সাবনেটটিই ধরে রাখে।
FAQ
কেন আমার কন্টেইনারগুলো সার্ভিস নেম ব্যবহার করে একে অপরের সাথে যোগাযোগ করতে পারছে না?
এগুলো একই নেটওয়ার্কে নেই। Compose স্বয়ংক্রিয়ভাবে প্রতিটি সার্ভিসকে <project>_default-এ যুক্ত করে, কিন্তু আপনি যখনই কোনো সার্ভিসে networks: তালিকা যোগ করেন, তখন সেই তালিকাটিই তার জন্য নেটওয়ার্কের সম্পূর্ণ সেট হয়ে যায় এবং ডিফল্ট নেটওয়ার্কটি আর কার্যকর থাকে না। docker network inspect <network> কমান্ডটি চালান এবং নিশ্চিত করুন যে উভয় কন্টেইনারই Containers ব্লকে দেখা যাচ্ছে। এছাড়া চেক করুন যে কোনো সার্ভিসই network_mode: host ব্যবহার করছে না, কারণ হোস্ট মোড কন্টেইনার কোনো Docker নেটওয়ার্কে থাকে না এবং সার্ভিস নেম রিজলভ করতে পারে না।
একটি সার্ভিস অন্যটির সাথে যোগাযোগ করার জন্য কি পোর্ট পাবলিশ করা প্রয়োজন?
না। একটি Compose নেটওয়ার্কে, ওই নেটওয়ার্কের অন্য সব কন্টেইনার থেকে প্রতিটি কন্টেইনারের সব পোর্টই অ্যাক্সেসযোগ্য। ports: শুধুমাত্র Docker-এর বাইরের ট্র্যাফিকের জন্য কন্টেইনারকে উন্মুক্ত করতে ব্যবহৃত হয় এবং expose: হলো ডকুমেন্টেশন। ডাটাবেস পোর্ট পাবলিশ করা একটি সাধারণ এবং ঝুঁকিপূর্ণ অভ্যাস, কারণ এটি ডাটাবেসকে আপনার সার্ভারের পাবলিক ইন্টারফেসে নিয়ে আসে।
ব্রিজ এবং হোস্ট নেটওয়ার্কিংয়ের মধ্যে পার্থক্য কী?
ব্রিজ নেটওয়ার্কিং কন্টেইনারকে একটি ভার্চুয়াল সুইচে নিজস্ব নেটওয়ার্ক নেমস্পেস এবং ঠিকানা দেয়, যার ফলে কন্টেইনারগুলোর মধ্যে স্বয়ংক্রিয় নেম রেজোলিউশন এবং আউটবাউন্ড ট্র্যাফিক ট্রান্সলেশন সম্ভব হয়। হোস্ট নেটওয়ার্কিং সরাসরি কন্টেইনারকে হোস্টের নেটওয়ার্ক স্ট্যাকের সাথে যুক্ত করে: এতে কোনো আলাদা ঠিকানা, সার্ভিস নেম দিয়ে রেজোলিউশন, পোর্ট পাবলিশিং বা হোস্টের অন্যান্য লিসেনারের থেকে কোনো আইসোলেশন থাকে না। ব্রিজ হলো ডিফল্ট এবং সঠিক পদ্ধতি, যদি না প্রসেসটির হোস্টের ইন্টারফেস ব্যবহারের প্রয়োজন হয়।
দুটি ভিন্ন Compose ফাইল থেকে কন্টেইনারগুলোকে কীভাবে সংযুক্ত করব?
docker network create edge ব্যবহার করে একটি শেয়ার্ড নেটওয়ার্ক তৈরি করুন, তারপর উভয় ফাইলে external: true দিয়ে সেটি ঘোষণা করুন এবং যে সার্ভিসগুলোর যোগাযোগের প্রয়োজন সেগুলোকে যুক্ত করুন। Compose এটি তৈরি বা ডিলিট করবে না। যদি আপনি তৈরির ধাপটি বাদ দেন, তবে Compose স্টার্ট হতে অস্বীকার করবে এবং নেটওয়ার্কটি এক্সটার্নাল হিসেবে ঘোষিত কিন্তু খুঁজে পাওয়া যায়নি বলে রিপোর্ট করবে।
UFW পোর্ট ব্লক করা সত্ত্বেও কেন আমার কন্টেইনার ইন্টারনেট থেকে অ্যাক্সেস করা যাচ্ছে?
কারণ একটি পাবলিশ করা পোর্ট Docker-এর iptables-এ যোগ করা ফরওয়ার্ডিং রুলস দ্বারা নিয়ন্ত্রিত হয়। এই রুলসগুলো UFW-এর রুলসের আগেই কার্যকর হয় এবং ফরওয়ার্ড করা ট্র্যাফিক কোনোভাবেই UFW ফিল্টার চেইনের মধ্য দিয়ে যায় না। হোস্ট সাইডকে "127.0.0.1:8080:80" দিয়ে লুপব্যাকে বাইন্ড করুন এবং পাবলিকলি অ্যাক্সেসযোগ্য যেকোনো কিছুকে পোর্ট 80 এবং 443-এ একটি রিভার্স প্রক্সির পেছনে রাখুন।