Rocky Linux বা AlmaLinux-এ Docker ইনস্টল করুন
dnf দিয়ে Docker Engine ও Compose plugin ইনস্টল করুন। Ubuntu guide-এর বাদ পড়া Podman-এর docker command দখল এবং SELinux bind mount সমস্যার সমাধানও দেখুন।
Rocky Linux এবং AlmaLinux-এ Docker ইনস্টল করুন
Rocky Linux বা AlmaLinux-এ Docker ইনস্টল করতে Docker-এর নিজস্ব dnf repository যোগ করুন, Compose plugin-সহ engine ইনস্টল করুন, তারপর service enable করুন। এই কাজের জন্য চারটি command লাগে। উভয় distribution-এ পদ্ধতিটি একই, কারণ দুটিই Red Hat Enterprise Linux (RHEL)-এর rebuild এবং একই package layout ব্যবহার করে। CentOS Stream-এও একই পদ্ধতি কাজ করে। নিচের সবকিছু উভয় distribution-এর জন্য প্রযোজ্য। তাই আপনি যদি এখনও দুটির মধ্যে নির্বাচন করে থাকেন, সিদ্ধান্তের প্রধান বিষয় হলো প্রতিটি project-এর compatibility promise এবং আপনার পুরোনো CPU এখনও supported কি না।
ইনস্টলেশন সংক্ষিপ্ত। তাই এই guide-এর বেশিরভাগ অংশে Ubuntu-এর তুলনায় Enterprise Linux (EL)-এর ভিন্ন আচরণ ব্যাখ্যা করা হয়েছে। আপনার image-এ Podman হয়তো ইতিমধ্যে docker command-এর দখল নিয়েছে। সঠিক label না থাকা পর্যন্ত SELinux bind-mounted file block করে। Firewalld Docker-এর published port filter করে না। তাই firewall-cmd কিছু open না দেখালেও কোনো container port Internet-এর জন্য খোলা থাকতে পারে।
get.docker.com থেকে Docker-এর convenience script ব্যবহার করবেন না। Docker-এর নিজস্ব documentation অনুযায়ী production-এর জন্য এটি recommended নয়। এটি অনুমতি না নিয়েই আপনার repository configuration পুনর্লিখে দেয় এবং upgrade করার জন্য নিরাপদভাবে আবার চালানো যায় না। Repository হাতে যোগ করলে dnf upgrade Docker-কে server-এর অন্য সব package-এর মতোই পরিচালনা করে। আপনার সিস্টেমে security update timer দিয়ে প্রয়োগ করা থাকলে এতে dnf-automatic-এর আওতায় Docker-ও চলে আসে। তাই শুরুতেই সিদ্ধান্ত নিন, Docker unattended অবস্থায় patch করবেন, নাকি maintenance window পর্যন্ত upgrade আটকে রাখবেন। যেকোনো ক্ষেত্রেই upgrade packaged binary প্রতিস্থাপন করে, কিন্তু পুরোনো dockerd চলতে থাকে। কোন service এখনও সদ্য প্রতিস্থাপিত code চালাচ্ছে তা জানাতে needs-restarting command ব্যবহার করা হয়।
podman কি ইতিমধ্যে docker command-এর উত্তর দিচ্ছে?
Rocky Linux এবং AlmaLinux তাদের default repository-তে podman সরবরাহ করে, এবং অনেক VPS image এটি আগে থেকেই install করে। কিছু image আরও এগিয়ে podman-docker install করে, যা /usr/bin/docker-এ একটি shell script রাখে এবং সেটি podman call করে। এরপর আপনি যে প্রতিটি docker command type করেন, তা podman চালায়। ফলে Docker-এর জন্য লেখা guide থেকে আপনার প্রত্যাশার বাইরে output আসতে পারে।
প্রথম লক্ষণটি হলো একটি banner। /usr/bin/docker script /etc/containers/nodocker file-টি পরীক্ষা করে। file-টি না থাকলে script কোনো কাজ করার আগে একটি line print করে:
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.কেউ banner বন্ধ করার জন্য file-টি তৈরি করে থাকতে পারে। তাই শুধু এই লক্ষণের ওপর নির্ভর করবেন না। কোন package binary-টির মালিক, তা package database-কে জিজ্ঞাসা করুন:
command -v docker
rpm -qf "$(command -v docker)"উত্তর podman-docker দিয়ে শুরু হলে podman command-এর উত্তর দিচ্ছে। উত্তর docker-ce-cli দিয়ে শুরু হলে সেটি আসল Docker। rpm -qf যদি জানায় যে কোনো package file-টির মালিক নয়, তাহলে কেউ এটি হাতে install করেছে। সে ক্ষেত্রে script-টি পড়ে না দেখে বিশ্বাস করবেন না।
Podman একই OCI image চালায় এবং এটি একটি যুক্তিসংগত পছন্দ। আপনি এটি ব্যবহার করতে চাইলে এখানেই থামতে পারেন। উভয়ই Linux container engine। তাই platform নির্বাচন এখনও চূড়ান্ত না হলে মনে রাখা ভালো যে FreeBSD jail registry থেকে আনা layered image চালানোর পরিবর্তে একটি সম্পূর্ণ userland isolate করে। আপনি Docker Engine ব্যবহার করতে চাইলে আগে conflicting package-গুলো সরান। RHEL-এর জন্য Docker যে তালিকাটি document করেছে, এটি সেটি:
sudo dnf remove docker docker-client docker-client-latest docker-common \
docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runcনিশ্চিত করার আগে dnf কোন package-গুলো সরানোর পরিকল্পনা করছে তা পড়ুন। একটি নতুন VPS image-এ তালিকাটি ছোট হয়। কিন্তু কোনো server আগে থেকেই ব্যবহার করা হয়ে থাকলে podman সরানোর কারণে cockpit-podman বা এর ওপর নির্ভরশীল অন্য কোনো tool-ও সরিয়ে যেতে পারে।
নীতিগতভাবে Docker-এর পাশাপাশি podman রাখা সম্ভব। এ ক্ষেত্রে শুধু podman-docker সরান, যাতে docker name-টি খালি থাকে, এবং runc সরান, যা containerd.io package প্রতিস্থাপন করে। Docker-এর documentation podman-কে একটি conflicting package হিসেবে বিবেচনা করে। তাই এই বিন্যাস Docker support করে না। install-এর সময় এখনও conflict report হলে ওপরের সম্পূর্ণ removal list ব্যবহার করুন।
dnf config-manager দিয়ে Docker-এর repository যোগ করুন
Docker Enterprise Linux-এর জন্য RPM প্রকাশ করে download.docker.com-এ। Repository file-টি CentOS tree নির্দেশ করে। Rocky Linux এবং AlmaLinux এই tree-টির সঙ্গেই resolve করে। Rocky সিস্টেমকে CentOS repository-তে নির্দেশ করা ভুল মনে হতে পারে, যতক্ষণ না আপনি 2020 সালে Red Hat CentOS-কে Stream-এ রূপান্তর করার পর উভয় distribution কীভাবে CentOS lineage থেকে গড়ে উঠেছে তা জানেন। August 2026-এ পরীক্ষা করে দেখা হয়েছে যে Docker CentOS Stream 9 এবং CentOS Stream 10-এর জন্য এই repository নথিভুক্ত করে।
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repodnf-এর Version 5-এ --add-repo argument বাদ দেওয়া হয়েছে। তাই নতুন release-এ দ্বিতীয় command ব্যর্থ হয়। আপনার কোন version আছে তা পরীক্ষা করুন। এরপর সামঞ্জস্যপূর্ণ form ব্যবহার করুন:
dnf --versionযদি 5.x version দেখায়, পরিবর্তে subcommand form ব্যবহার করুন:
sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/centos/docker-ce.repoউভয় command-ই /etc/yum.repos.d/docker-ce.repo-এ একই file লেখে। ভুল form-টি unknown-argument error দিয়ে ব্যর্থ হয়। এটি নীরবে ভুল কোনো কাজ করে না। তাই আপনি সমস্যাটি বুঝতে পারবেন।
এই repo file-এ baseurl এমন একটি path-এ সেট করা থাকে, যেখানে $releasever রয়েছে। dnf আপনার release package থেকে এই variable-এর মান নিয়ে সেটি expand করে। Rocky Linux এবং AlmaLinux এটিকে major version number-এ সেট করে। তাই EL 9-এ 9 এবং EL 10-এ 10 হয়। এই কারণেই Rocky সিস্টেমে CentOS repository সঠিকভাবে resolve করে। Install করার আগে expansion নিশ্চিত করুন:
sudo dnf repoinfo docker-ce-stableRepo-baseurl line পড়ুন। এটি /9/x86_64/stable অথবা /10/x86_64/stable দিয়ে শেষ হওয়া উচিত। আপনার release যদি $releasever-কে 9.6-এর মতো point version-এ সেট করে, metadata fetch করার সময় dnf ওই URL-এর জন্য Status code: 404 দেখায়। এটি ঠিক করতে /etc/yum.repos.d/docker-ce.repo edit করুন এবং $releasever-এর বদলে শুধু major number লিখুন।
ইঞ্জিন ও compose plugin ইনস্টল করুন
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginপাঁচটি package আছে, এবং প্রতিটির কাজ আলাদা। docker-ce হলো daemon, dockerd। docker-ce-cli হলো আপনি যে docker command টাইপ করেন। containerd.io হলো daemon যে container runtime চালায়। docker-buildx-plugin image তৈরি করে। docker-compose-plugin docker compose-কে একটি subcommand হিসেবে সরবরাহ করে।
এই package-গুলো hyphen-যুক্ত docker-compose binary ইনস্টল করে না। এটি ছিল Compose v1, যার জীবনচক্র July 2023-এ শেষ হয়েছে। যে কোনো configuration বা script যদি hyphen-যুক্ত docker-compose ব্যবহার করে, সেটিকে space-সহ docker compose-এ আপডেট করতে হবে।
প্রথম install-এর সময় Docker-এর signing key import করার জন্য প্রক্রিয়া থামবে এবং fingerprint দেখাবে। এই key সদ্য যোগ করা repo file-এর gpgkey=https://download.docker.com/linux/centos/gpg থেকে আসে। তাই key গ্রহণ করার আগে dnf যে fingerprint দেখায়, সেটি ওই URL-এর fingerprint-এর সঙ্গে মিলিয়ে নিন।
একটি failure এত ঘন ঘন দেখা যায় যে সেটিকে আলাদা করে উল্লেখ করা দরকার। dnf যদি জানায় যে containerd.io-এর জন্য container-selinux প্রয়োজন, কিন্তু কোনো package সেটি সরবরাহ করছে না, তাহলে আপনার AppStream repository disabled। dnf repolist চালান এবং appstream তালিকাভুক্ত আছে কি না নিশ্চিত করুন, কারণ EL 9 ও EL 10-এ container-selinux এখান থেকেই release হয়।
Docker চালু করুন এবং এটি চলছে কি না নিশ্চিত করুন
sudo systemctl enable --now docker
sudo systemctl status docker --no-pager
sudo docker run --rm hello-worldDocker-এর RPM package ইনস্টল করার পরে daemon-কে stopped ও disabled অবস্থায় রাখে। এ কারণেই এই ধাপটি Docker-এর CentOS page-এ আছে, কিন্তু Ubuntu page-এ নেই; Ubuntu-তে deb package আপনার হয়ে service চালু করে। enable বাদ দিলে Docker পরবর্তী reboot পর্যন্ত চলে। এরপর এটি বন্ধ থাকে এবং এর সঙ্গে সব container-ও বন্ধ হয়ে যায়।
systemctl status-এর আউটপুটে Active: active (running) দেখা উচিত। hello-world container-টি This message shows that your installation appears to be working correctly. print করে exit করা উচিত। এর পরিবর্তে /var/run/docker.sock-এ permission error দেখালে আপনি sudo বাদ দিয়েছেন। নিচের docker group section-এ এর সমাধান দেখানো হয়েছে।
Compose plugin আলাদাভাবে পরীক্ষা করুন। এটি একটি পৃথক package, তাই engine ঠিক থাকলেও plugin অনুপস্থিত থাকতে পারে:
docker compose versionসুস্থ অবস্থায় উত্তরটি Docker Compose version v2.x.x-এর মতো দেখায়। reboot-এর পরে আপনার service-গুলো ফিরিয়ে আনা daemon enable করার থেকে আলাদা বিষয়। restart policy নির্ধারণ করে boot-এর সময় Compose service-গুলো ফিরে আসবে কি না।
bind mount-এ permission denied কেন দেখায়?
Rocky Linux এবং AlmaLinux-এ ডিফল্টভাবে SELinux (Security-Enhanced Linux) enforcing mode-এ চলে। getenforce চালিয়ে এটি নিশ্চিত করুন; কমান্ডটি Enforcing দেখায়।
Docker container-গুলো SELinux type container_t-এর অধীনে চলে। এই type কেবল container_file_t label-যুক্ত file পড়তে ও লিখতে পারে। Host-এ তৈরি করা directory তার parent path থেকে যে label পায়, সেটি container_file_t নয়। Host side থেকে owner, group এবং mode সঠিক দেখালেও container-কে access থেকে বিরত রাখা হয়। তিনটি command-এ এটি পুনরায় তৈরি করুন:
sudo mkdir -p /srv/site
echo hello | sudo tee /srv/site/index.html
sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro nginx:alpine cat /usr/share/nginx/html/index.htmlContainer দেখায়:
cat: can't open '/usr/share/nginx/html/index.html': Permission deniedদুটি command কারণটি দেখায়। ls -ldZ /srv/site label দেখায়। /srv-এর অধীনে থাকা path-এর ক্ষেত্রে label হলো system_u:object_r:var_t:s0, container_file_t নয়। এরপর sudo ausearch -m avc -ts recent kernel-এর audit record দেখায়। এতে avc: denied { read } থাকে, যা container_t-এর নাম নির্দেশ করে এমন একটি scontext= field, এবং tcontext= field-এ directory-তে আপনি যে label দেখেছেন সেটির নাম থাকে। এই দুই field-এর অমিলই পুরো সমস্যার কারণ।
Volume argument-এ suffix যোগ করলেই সমস্যাটি ঠিক হয়। Docker আপনার হয়ে path-টি relabel করে:
sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro,z nginx:alpine cat /usr/share/nginx/html/index.htmlছোট হাতের :z content-কে shared হিসেবে relabel করে, তাই একাধিক container একই directory ব্যবহার করতে পারে। বড় হাতের :Z content-কে private এবং unshared হিসেবে relabel করে। এটি একটি container-এর সঙ্গে যুক্ত থাকে, ফলে দ্বিতীয় কোনো container একই path পড়তে গেলে access থেকে বঞ্চিত হয়। Sidecar বা backup container-ও যে directory ব্যবহার করে, সেখানে :z ব্যবহার করুন। একটি container-এর অধীনে থাকা database directory-র জন্য :Z ব্যবহার করুন।
Docker-এর documentation-এ একটি গুরুত্বপূর্ণ সতর্কতা রয়েছে, কারণ relabel recursive। :Z সহ /home বা /usr-এর মতো system directory bind-mount করলে তা “আপনার host machine-কে অচল করে দিতে পারে এবং আপনাকে host machine-এর file হাতে relabel করতে হতে পারে”। এই suffix-গুলো কেবল container-এর জন্য তৈরি করা directory-তে ব্যবহার করুন। কখনো system path-এ ব্যবহার করবেন না।
Compose-এ একই string-এর শেষে suffix দিতে হয়:
services:
web:
image: nginx:alpine
volumes:
- /srv/site:/usr/share/nginx/html:ro,zদুটি সীমাবদ্ধতা সহজেই সমস্যার কারণ হতে পারে। --mount flag কোনো SELinux label সেট করতে পারে না। তাই label প্রয়োজন হলে -v ব্যবহার করুন। Named volume-এ suffix প্রয়োজন হয় না, কারণ Docker নিজেই /var/lib/docker/volumes-এর অধীনে তৈরি করা directory-গুলো label করে।
SELinux বন্ধ করবেন না। এক মিনিটের পরীক্ষার জন্য শুধু sudo setenforce 0 ব্যবহার করুন। এরপর container কাজ করলে বুঝবেন সমস্যাটি label-সংক্রান্ত, এবং :z-ই সমাধান। সঙ্গে সঙ্গে sudo setenforce 1 দিয়ে SELinux আবার চালু করুন। Enterprise Linux-এ bind mount-এ permission denied-এর দুটি পৃথক কারণ থাকতে পারে, যদিও container-এর ভেতর থেকে দুটিই একই রকম দেখায়। একটি হলো SELinux label। অন্যটি হলো সাধারণ numeric user এবং group ownership, যা সমাধানের জন্য PUID এবং PGID variable ব্যবহৃত হয়। ls -lnZ এক লাইনে mode, numeric owner এবং label দেখায়। ফলে আপনি বুঝতে পারবেন কোন সমস্যাটি সমাধান করতে হবে।
প্রকাশিত port firewalld বন্ধ দেখালেও কেন reachable থাকে?
Rocky Linux এবং AlmaLinux-এ firewalld ডিফল্ট firewall। sudo systemctl is-active firewalld দিয়ে এটি চলছে কি না পরীক্ষা করুন। এই সার্ভারে এখনও firewalld configure না করে থাকলে আগে firewalld দিয়ে SSH এবং একটি web port খোলা সম্পন্ন করুন। কারণ নিচের আচরণটি বোঝার জন্য কাজ করা zone ruleset-এর সঙ্গে তুলনা করা দরকার। এবার একটি port publish করে firewalld কোন port খোলা মনে করছে তা দেখুন:
sudo docker run -d --name web -p 8080:80 nginx:alpine
sudo firewall-cmd --list-portsfirewall-cmd একটি খালি line print করে। অন্য একটি machine থেকে curl -I http://YOUR_SERVER_IP:8080/ চালালে HTTP/1.1 200 OK ফেরত আসে। Port-টি Internet-এর জন্য খোলা, কিন্তু firewall কিছুই রিপোর্ট করছে না।
এর কারণ packet যে path দিয়ে যায়। Firewalld-এর zone rules host নিজেকে উদ্দেশ্য করে পাঠানো traffic filter করে। Published port host-কে উদ্দেশ্য করে পাঠানো হয় না। Packet host-এর input path-এ পৌঁছানোর আগেই Docker একটি destination NAT (network address translation) rule বসিয়ে destination container-এর address-এ rewrite করে। তাই kernel packet-টি locally deliver না করে forward করে। এরপর Docker তার bridge interface-গুলোকে docker নামের firewalld zone-এ রাখে। এই zone-এর target হলো ACCEPT। Docker docker-forwarding নামে একটি forwarding policy-ও যোগ করে, যা যেকোনো zone থেকে docker zone-এ forwarding অনুমোদন করে। আপনার zone rules packet-টি দেখতে পায় না।
সবচেয়ে পরিষ্কার সমাধানের জন্য কোনো firewall rule দরকার হয় না। Host-side publish-টি loopback-এ bind করুন এবং এর সামনে একটি reverse proxy রাখুন:
sudo docker rm -f web
sudo docker run -d --name web -p 127.0.0.1:8080:80 nginx:alpine
curl -I http://127.0.0.1:8080/Local curl, HTTP/1.1 200 OK ফেরত দেয়। অন্য machine থেকে একই request আর connect করতে পারে না। -p argument-এ host address না থাকলে port-টি প্রতিটি interface-এ publish হয়। তাই খালি -p 8080:80-কে service-টি public Internet-এ expose করার সিদ্ধান্ত হিসেবে বিবেচনা করুন।
কোনো service কিছু address থেকে reachable রাখা এবং অন্য address থেকে অযোগ্য রাখতে হলে Docker আপনার জন্য একটি chain নির্ধারণ করে। DOCKER-USER Docker-এর নিজস্ব accept rule-এর আগে process হয়। তাই সেখানে যোগ করা rule Docker restart করে chain rewrite করলেও টিকে থাকে:
sudo iptables -I DOCKER-USER -i enp1s0 ! -s 203.0.113.10 -j DROP
sudo iptables -S DOCKER-USERip route show default থেকে interface name নিন। eth0 ধরে নেবেন না। বর্তমান EL image-গুলোতে enp1s0 বা ens3-এর মতো name ব্যবহৃত হয়। Rocky এবং AlmaLinux-এ iptables command হলো nftables-এর একটি compatibility layer। এর মাধ্যমেই Docker-এর chain দেখা যায়। এভাবে যোগ করা rule reboot-এর পরে মুছে যায়, যদি না সেগুলো save করেন। Rule-গুলো আপনার পছন্দমতো ঠিক হলে একটি systemd unit-এ লিখে রাখুন।
2025 সালে release হওয়া Docker Engine 28.0 একটি কাছাকাছি security gap বন্ধ করেছে। আগে publish না করা container port-এ direct routed access সম্ভব ছিল। এখন DOCKER chain-এ সেটি block করা হয়। এই পরিবর্তন published port-এ প্রভাব ফেলে না। তাই বর্তমান version-এও উপরের নির্দেশনা প্রযোজ্য। একটি operational অভ্যাস গড়ে তুলুন: যেকোনো sudo firewall-cmd --reload-এর পরে published port আবার test করুন। Port response না দিলে sudo systemctl restart docker Docker-এর rule পুনরায় install করে।
Ubuntu administrator-রা অন্য tool-এর মাধ্যমে একই সমস্যার মুখোমুখি হন। এটি হলো published Docker port কেন ufw rule উপেক্ষা করে। উভয় ক্ষেত্রেই কারণ NAT path। শুধু এর সামনে থাকা firewall পরিবর্তিত হয়।
root ছাড়া একজন user-কে docker group-এ যোগ করুন
প্রতিটি docker command-এর আগে sudo লিখতে থাকলে বিরক্তিকর লাগে। docker group এই প্রয়োজন দূর করে:
sudo usermod -aG docker $USER
newgrp docker
docker run --rm hello-worldusermod -aG /etc/group সম্পাদনা করে। তবে আপনার বর্তমান shell-এ group list আগেই নির্ধারিত আছে। তাই নতুন group list না পাওয়া পর্যন্ত পরিবর্তনটি কার্যকর হবে না। newgrp docker group সংযুক্ত একটি নতুন shell চালু করে, যাতে আপনি সঙ্গে সঙ্গে পরীক্ষা করতে পারেন। নতুন SSH session-এ এটি স্বয়ংক্রিয়ভাবে কার্যকর হবে।
এই group কী সুবিধা দেয়, তা স্পষ্টভাবে বুঝুন। এই group-এর সদস্য হলে /var/run/docker.sock-এ write access পাওয়া যায়। ওই socket-এর সঙ্গে কথা বলতে পারে এমন যেকোনো কিছু daemon-কে host filesystem mount করা একটি container চালু করতে বলতে পারে। একটি command-এই এর অর্থ দেখা যায়:
docker run --rm -v /:/host alpine wc -l /host/etc/shadowএটি এমন একটি file পড়ে, যা শুধু root পড়তে পারে। অথচ এটি এমন একটি account থেকে চালানো হয়, যার কোনো sudo অধিকার নেই। Docker-এর নিজস্ব post-install documentation-এও একই কথা বলা হয়েছে: docker group root-এর সমতুল্য privilege দেয়। কোনো account-কে এই group-এ যোগ করুন কেবল তখনই, যখন সেই account-কে sudo দেওয়ার সিদ্ধান্তও নেবেন। নতুন server-এ account তৈরি করলে, পরে নয়, শুরুতেই আপনার VPS-এ least-privilege user setup-এর অন্যান্য সিদ্ধান্তের সঙ্গে এটি নির্ধারণ করুন।
Docker একটি rootless mode-ও সরবরাহ করে, যেখানে daemon unprivileged user হিসেবে চলে। এটি আলাদা install path। এতে storage driver এবং 1024-এর নিচের port কীভাবে কাজ করে, তা পরিবর্তিত হয়। তাই এটিকে পরে যোগ করা একটি flag হিসেবে নয়, বরং আলাদা project হিসেবে পরিকল্পনা করুন।
এরপর কোথায় যাবেন
এখন আপনার কাছে engine, compose plugin, reboot-এর পরেও চালু থাকা একটি service এবং EL-নির্দিষ্ট তিনটি আচরণের উপরের নথি রয়েছে। পরবর্তী ধাপ হলো প্রতি service-এর জন্য একটি compose.yaml তৈরি করা। Compose file-এর গঠন-এ file format এবং এটি পরিচালনার command-গুলো ব্যাখ্যা করা হয়েছে। এটি যদি আপনার প্রথম container host হয়, তাহলে VPS-এ Docker চালানো অংশে এই guide-এ বাদ পড়া sizing, storage এবং image hygiene-সংক্রান্ত বিষয়গুলো ব্যাখ্যা করা হয়েছে।
FAQ
Docker-এর CentOS repository কি Rocky Linux এবং AlmaLinux-এ কাজ করে?
হ্যাঁ। https://download.docker.com/linux/centos/docker-ce.repo-এর সঙ্গে dnf config-manager যোগ করুন। ওই ফাইলের baseurl-এ $releasever থাকে, এবং Rocky Linux ও AlmaLinux সেটিকে major version number-এ প্রসারিত করে। তাই EL 9 সিস্টেমে CentOS 9 tree এবং EL 10 সিস্টেমে CentOS 10 tree নির্ধারিত হয়। sudo dnf repoinfo docker-ce-stable দিয়ে expansion নিশ্চিত করুন এবং Repo-baseurl line পড়ুন। dnf metadata fetch করার সময় Status code: 404 দেখা গেলে বুঝবেন variable-টি point release-এ প্রসারিত হয়েছে। /etc/yum.repos.d/docker-ce.repo সম্পাদনা করে bare major number ব্যবহার করলে সমস্যাটি ঠিক হয়।
একই server-এ Docker এবং podman কি ইনস্টল করা যায়?
Docker-এর documentation-এ podman এবং runc-কে conflicting package হিসেবে উল্লেখ করা হয়েছে এবং Docker Engine ইনস্টল করার আগে দুটিই সরিয়ে ফেলতে বলা হয়েছে। আসল সংঘাতটি podman-docker package-কে ঘিরে। এটি /usr/bin/docker-এর মালিক এবং প্রতিটি docker command-কে podman command-এ পরিণত করে। কোন package ওই path-এর মালিক তা দেখতে rpm -qf "$(command -v docker)" চালান। Output podman-docker দিয়ে শুরু হলে podman command-টির উত্তর দিচ্ছে। দুটি engine একসঙ্গে রাখা Docker সমর্থিত layout নয়। তাই গুরুত্বপূর্ণ server-এ একটি বেছে নিন।
Bind mount-এ আমার container কেন permission denied দেখায়?
Rocky Linux এবং AlmaLinux-এ ডিফল্টভাবে SELinux enforcing অবস্থায় থাকে। Container-গুলো container_t type হিসেবে চলে এবং শুধু container_file_t label-যুক্ত file-এ access করতে পারে। তাই আপনার তৈরি directory-তে ভুল label থাকলে owner ও mode সঠিক হলেও access denied হয়। Host path-এ ls -ldZ এবং sudo ausearch -m avc -ts recent চালিয়ে এটি নিশ্চিত করুন। sudo ausearch -m avc -ts recent দুটি অসামঞ্জস্যপূর্ণ context-সহ avc: denied print করে। Container-গুলোর মধ্যে shared content-এর জন্য volume argument-এ :z যোগ করুন। একটি container-এর জন্য private content হলে :Z ব্যবহার করুন। :Z-কে কখনো /home বা /usr-এর দিকে নির্দেশ করবেন না। Relabel recursive হওয়ায় host ক্ষতিগ্রস্ত হবে।
Container port publish করতে কি firewalld-এ port খুলতে হবে?
না, এবং সমস্যাটি এখানেই। Packet host-এর input path-এ পৌঁছানোর আগেই Docker-এর NAT rule destination address পরিবর্তন করে। তাই firewalld-এর zone rule packet-টি পরীক্ষা করে না। Docker তার bridge-গুলোকে docker নামের firewalld zone-এ রাখে, যার target ACCEPT। -p 8080:80 দিয়ে শুরু করা container Internet থেকে reachable হয়, যদিও sudo firewall-cmd --list-ports কিছুই print করে না। শুধু host থেকে service-এ access প্রয়োজন হলে -p 127.0.0.1:8080:80 দিয়ে নির্দিষ্ট address-এ publish করুন। অথবা DOCKER-USER chain-এ filtering rule যোগ করুন। Docker নিজের accept rule-এর আগে এই chain process করে।
আমার user-কে docker group-এ যোগ করা কি নিরাপদ?
এতে root access প্রদান করা হয়। docker group-এর member /var/run/docker.sock-এ লিখতে পারে। এরপর docker run --rm -v /:/host alpine wc -l /host/etc/shadow sudo অধিকার না থাকা account থেকেও root-only file পড়তে পারে। Docker-এর post-install documentation-এও একই equivalence বলা হয়েছে। যেসব account-কে আপনি আগে থেকেই sudo-এর সমতুল্য অধিকার দিতে বিশ্বাস করেন, শুধু সেগুলো যোগ করুন। Shared বা service account-এর জন্য sudo docker ব্যবহার চালিয়ে যান। Unprivileged user-এর অধীনে container চালানোর প্রয়োজন হলে rootless mode বিকল্প। এটি একটি পৃথক install path, কোনো setting নয়।