কম্পিউটার টিউটোরিয়াল

ডকার কন্টেইনার: Новиসদের জন্য সম্পূর্ণ গাইড - সেটআপ, ব্যবহার এবং সেরা অনুশীলন

এক বড় প্রতিশ্রুতির সাথে শুরু করছি: আপনি আজ এই আর্টিকেলকে ভালোবাসবেন। এটি লম্বা, বিস্তারিত এবং অত্যন্ত উপকারী। GRUB, GRUB2-এর মতোই এখানেও একই কথা—শুধু এখানে Docker, একটি সুন্দর ডিস্ট্রিবিউশন প্ল্যাটফর্ম যা Linux Containers (LXC) টেকনোলজিকে সহজ ও সুবিধাজনকভাবে লپیয়ে দিয়েছে।

আমি দেখাবো কীভাবে শুরু করতে হয়, তারপর আমরা SSH এবং Apache-এর সাথে নিজস্ব কন্টেইনার তৈরি করব, Dockerfile ব্যবহার শিখব, সার্ভিস পোর্ট এক্সপোজ করব, এবং অসংখ্য ছোট বাগ ও সমস্যা সমাধান করব যা সাধারণত পাবলিক ফোরামে আলোচনা হয় না। চলুন শুরু করা যাক।

সামগ্রীসূচি

  1. প্রস্তাবনা
  2. Docker ইমপ্লিমেন্টেশন
  3. শুরু করা
  4. Docker কমান্ডগুলো
  5. ইমেজ পুল করা
  6. Docker কন্টেইনার চালু করা
  7. Apache এবং SSH ইনস্টল
    1. সার্ভিস চালু করা
    2. Apache সার্ভিস
    3. SSH সার্ভিস
  8. Web সার্ভার চেক করা
    1. ইনকামিং পোর্ট এক্সপোজ করা
    2. IP ঠিকানা চেক করা
    3. নতুন কনফিগারেশন টেস্ট করা
  9. SSH কাজ করছে কিনা চেক করা
    1. রুট পাসওয়ার্ড কী?
  10. ইমেজ কমিট করা
  11. Dockerfile
    1. ইমেজ বিল্ড করা
    2. ইমেজ টেস্ট করা
  12. বিকল্প বিল্ড
    1. COPY ইনস্ট্রাকশন
  13. কন্টেইনারের সুবিধাগুলো
  14. সামালিয়ে gặpতে পারে এমন সমস্যা ও ট্রাবলশুটিং
  15. অতিরিক্ত কমান্ডগুলো
    1. exec এবং attach-এর পার্থক্য
    2. start এবং run-এর পার্থক্য
    3. build এবং create-এর পার্থক্য
  16. এটা শুধু শুরু...
  17. আরো পড়ুন
  18. উপসংহার

প্রস্তাবনা

গত বছর Gizmo's Freeware-এ আমি এই টেকনোলজির সংক্ষিপ্ত ওভারভিউ দিয়েছিলাম। এখন Docker-র সাথে רצינית হবার পালা। প্রথমে মনে রাখতে হবে: এই ফ্রেমওয়ার্ক আপনাকে LXC ব্যবহার করতে দেয় সব ঝামেলা ছাড়া। এটা ভার্চুয়ালাইজেশন জগতের OpenStack-এর মতো পরবর্তী ধাপ। কিছু ইতিহাস এবং аналоги দিয়ে ব্যাখ্যা করছি।

ভার্চুয়ালাইজেশন শুরু হয়েছিল হার্ডওয়্যার অ্যাবস্ট্র্যাকশন দিয়ে। তারপর হার্ডওয়ার এক্সিলারেশন, প্যারাভার্চুয়ালাইজেশন এসেছে। শেষে হাইপারভাইজরها মশরুমের মতো ছড়িয়ে পড়েছে এবং সাবগুলো ম্যানেজ করা কঠিন হয়ে উঠেছে। এই সমস্যাই OpenStack-এর কারণ—বিভিন্ন প্ল্যাটফর্মকে একীভূত API-এর নিচে আনা।

কন্টেইনারও একই পথে এগিয়েছে। প্রথমে chroot ছিল, কিন্তু একই নেমস্পেস ও রিসোর্স শেয়ার করত। তারপর kexec সিস্টেম কল এসেছে, যা BIOS ছাড়া অন্য কার্নেলের কনটেক্সটে বুট করতে দেয়। следে control groups (cgroups) এসেছে, যা CPU, মেমরি ইত্যাদি রিসোর্স পার্টিশন করতে দেয়।

বादে লিনাক্স কার্নেল ফুল রিসোর্স আইসোলেশন দিয়েছে cgroups ব্যবহার করে। টেকনিক্যালি এটা সিস্টেম-লেভেল ভার্চুয়ালাইজেশন—কন্ট্রোল হোস্টের ওপর একাধিক কার্নেল ইনস্ট্যান্স চালাতে দেয় আত্মনির্ভর এনভায়রনমেন্টে, খুব কম পারফরম্যান্স পেনাল্টি ও ওভারহেডের সাথে।

OpenVZ-এর মতো প্রতিযোগী টেকনোলজি ছিল, কিন্তু কমিউনিটি মেইনলাইন কার্নেলে নেটিভ ইনাবলমেন্টে ফোকাস করল। LXC একটু কঠিন থাকলেও, কারণ টেকনিক্যাল নলেজ ও স্ক্রিপ্টিং লাগে।

এখানেই Docker এসে পড়েছে। এটি গ্রিটি 부분을 সরিয়ে সহজ পদ্ধতি দিয়ে কন্টেইনার স্পান করতে দেয় ব্যাকএন্ড ইনফ্রাস্ট্রাকচার চিন্তা ছাড়া। প্রায়। কিন্তু 난이도가 훨 কম।

Docker-এর অন্য বড় সুবিধা: وسیع কমিউনিটি স্বীকৃতি এবং ক্লাউড সার্ভিসের সাথে ইন্টিগ্রেশনের জোর। AWS, Hadoop, Azure, Jenkins-এর মতো বড় নামগুলো। Platform as a Service (PaaS) কনসেপ্টও এসেছে—আসন্ন বছরে কতটাকা ও ফোকাস আসবে সেটা কল্পনা করুন। টেকনোলজিক্যাল ландস্কেপ বিশাল ও গুলগুলি, এটা আরো পরিবর্তন ও বিবর্তন হবে, নতুন কনসেপ্ট ও র‍্যাপার টেকনোলজি Docker-এর ওপর বিল্ড হয়ে উঠবে।

আমরা টেকনোলজিক্যাল দিকটাই ফোকাস করব। বেসিক শিখে ধীরে ধীরে ইন্টিগ্রেশন ক্যাপাবিলিটি, ফ্লেক্সিবিলিটি ব্যবহার করে ক্লাউড ইকোসিস্টেম এক্সপার্টিজ বড় করব। আজ নয়, কিন্তু আমি আপনাকে প্রথম কয়েক মাইল নেভিগেট করতে সাহায্য করব যাতে Docker সেন্সিবলি ও ইফিশিয়েন্টলি ব্যবহার করতে পারেন। যেহেতু যুব টেকনোলজি, ডকুমেন্টেশন প্রায় সকলই পুরনো, কপি-পেস্ট, অসম্পূর্ণ। আজ সেটা ঠিক করব।

Docker ইমপ্লিমেন্টেশন

কিছু বোরিং কথা আরেকটু। Docker মূলত LXC-র ওপর ভিত্তি করে তৈরি, কিন্তু শুধু সেটা নয়। এটি এক্সটেনসিবল ডিজাইন করা হয়েছে এবং libvirt ও systemd-র সাথে ইন্টারফেস করতে পারে। একভাবে হাইপার-হাইপারভাইজর—ভবিষ্যতে আরও মডিউল যোগ হলে Xen বা KVM বা libvirt-ভিত্তিক যেকোনো ক্লাসিক হাইপারভাইজারকে রিপ্লেস করতে পারে।

এটা পাবলিক ডোমেইন ইমেজ, যদি জানতে চান।

শুরু করা

আমরা CentOS 7-এ ডেমো করব। Ubuntu না। অনলাইনের অধিকাংশ স্টাফ Ubuntu-কेंद्रিক, কিন্তু আমি এন্টারপ্রাইজ-ফ্লেভার লিনাক্সে কীভাবে করা যায় সেটা দেখাতে চাই, কারণ Docker ব্যবহার করলে সেটা বізনেস এনভায়রনমেন্টে হবেই। প্রথম কাজ: Docker ইনস্টল।

yum install docker-io

ইনস্টল হলে ব্যবহার শুরু করা যায়। কিন্তু প্রথমবার Docker কমান্ড চালালে দুটি সমস্যা হতে পারে:

docker <any one command>
FATA[0000] Get https:///var/run/docker.sock/v1.18/images/json: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?

এবং আর একটি এরর:

docker <any one command>
FATA[0000] Get https:///var/run/docker.sock/v1.18/containers/json: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?

কারণ: Docker সার্ভিস শুরু করতে হবে। 더불어 Docker রুট হিসেবে চালাতে হয়, কারণ সিস্টেমের সেনসিটিভ অংশ ও কার্নেলের সাথে ইন্টারঅ্যাক্ট করতে হয়।

systemctl start docker

এখন Docker দিয়ে পাগলামি শুরু করা যাক।

Docker কমান্ডগুলো

বেসিক: docker help চালিয়ে উপলব্ধ কমান্ডগুলো দেখুন। সব অপশন এখানে বলব না। আমরা আগাম জানব। সন্দেহ হলে অনলাইন ডকুমেন্টেশন দেখুন। CLI রেফারেন্স ও GitHub-এ চিটশিট ভালো। আমাদের প্রথম মিশন: নতুন Docker ইমেজ ডাউনলোড করে প্রথম ইনস্ট্যান্স চালানো।

ইমেজ পুল করা

অনেক ইমেজ আছে। আমরা CentOS-এ প্র্যাকটিস করব। অফিসিয়াল রিপোজিটরি আছে যেটা সব সাপোর্টেড ইমেজ ও ট্যাগ লিস্ট করে। Docker ইমেজ কীভাবে লেবেল করা হয় সেটা বুঝতে হবে।

নেমিং কনভেনশন: repository:tag, যেমন centos:latest। মানে লেটেস্ট CentOS ইমেজ। কিন্তু হতে পারে centos:6.6। চলুন করি।

docker images কমান্ড দিয়ে লিস্ট করা যাক।

Docker কন্টেইনার চালু করা

আমার মূল টিউটোরিয়ালে দেখা গিয়েছিল, সিম্পল উদাহরণ: শেল চালানো।

docker run -ti centos:centos7 /bin/bash

এখানে কী হচ্ছে? -t (TTY) এবং -i (STDIN) দিয়ে CentOS 7 ইমেজ থেকে নতুন কন্টেইনার ইনস্ট্যান্স চালালাম BASH শেলসহ। কয়েক সেকেন্ডে কন্টেইনারের ভিতর নতুন শেল পাবেন। এটি খুব বেসিক, স্ট্রিপড-ডাউন OS, কিন্তু এর ভিতরে বিল্ড আপ করা যাবে।

Apache ও SSH ইনস্টল

Web সার্ভার সেটআপ করব SSH অ্যাক্সেসসহ। Apache (httpd) এবং SSHD (openssh-server) গ্র্যাব করে কনফিগার করব। এটা Docker-এর সাথে সরাসরি জড়িত নয়, কিন্তু সার্ভিস সেটআপ ও রান শিখতে উপকারী এক্সারসাইজ।

কেউ বলতে পারে: কন্টেইনারে SSH লাগে না, সিকিউরিটি রিস্ক। হ্যাঁ, নয়—ডিপেন্ড করে আপনার 니ড ও ইউজ কেস। সিকিউরিটি বিবেচনা বাদ দিয়ে শুধু যেকোনো সার্ভিস সেটআপ ও রান শিখব।

সার্ভিস চালু করা

Apache.init স্ক্রিপ্ট বা systemd কমান্ড দিয়ে চালাতে চাইলে কাজ করবে না। CentOS systemd-সহ আসে, কিন্তু কন্টেইনারের নিজস্ব systemd নেই। চেষ্টা করলে ফেইল:

systemctl start httpd
Failed to get D-Bus connection: No connection to service manager.

এই সমস্যা সমাধানের হ্যাক আছে, ভবিষ্যতে আলোচনা করব। কিন্তু কন্টেইনার হালকা ও সিম্পল হলে ফুল-ফ্লেজড স্টার্টআপ সার্ভিস লাগে না। কিছু কমপ্লেক্সিটি যোগ হয়।

Apache সার্ভিস

Apache (HTTPD) চালাতে /usr/sbin/httpd এক্সিকিউট করুন। সার্ভিস শুরু হবে, কিন্তু ServerName ডিরেক্টিভ httpd.conf-এ কনফিগার না থাকলে ওয়ার্নিং দেবে। আমার Apache গাইডে শিখেছি কীভাবে ফিক্স করতে হয়।

/usr/sbin/httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message

SSH সার্ভিস

SSHD চালাতে /usr/sbin/sshd।

/usr/sbin/sshd -f /etc/ssh/sshd_config
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_dsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key

ফেইল হবে, কারণ সব কী নেই। সাধারণত স্টার্টআপ স্ক্রিপ্ট এই কেয়ার নেয়, তাই সার্ভিস শুরু করার আগে একবার ssh-keygen চালাতে হবে। যেকোনো একটা কাজ করবে:

/usr/bin/ssh-keygen -t rsa -f <path to file>
/usr/bin/ssh-keygen -A
ssh-keygen: generating new host keys: RSA1 RSA DSA ECDSA ED25519

Web সার্ভার আপ কিনা চেক করা

কন্টেইনারের ভিতরে Apache চলছে কিনা দেখি:

ps -ef|grep apache
apache 87 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 88 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 89 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 90 86 0 10:47 ? 00:00:00 /usr/sbin/httpd
apache 91 86 0 10:47 ? 00:00:00 /usr/sbin/httpd

বাহির থেকে কানেক্টিভিটি চেক করতে চাইলে? দুটি সমস্যা: পোর্ট খোলা নেই, এবং কন্টেইনারের IP জানি না। কন্টেইনারের ভিতর ifconfig চালালেও কাজ করবে না—নেটওয়ার্কিং কমান্ডের প্যাকেজ ইনস্টলড নেই। ভালো話, কন্টেইনার স্লিম ও সিকিউর থাকে।

ইনকামিং পোর্ট এক্সপোজ করা

Web সার্ভারের মত ডিফল্ট পোর্ট 80 খোলা দরকার। রাউটারের পোর্ট ফরোয়ার্ডিং/ফায়ারওয়াল পলিসির মতো। Docker-এ একাধিক পদ্ধতিতে করা যায়।

run কমান্ডে -p অপশন দিয়ে পোর্ট স্পেসিফাই করা যায়। সিঙ্গল পোর্ট বা রেঞ্জ, এবং হোস্ট পোর্ট (hostPort) ও কন্টেইনার পোর্ট (containerPort) ম্যাপ করা যায়। উদাহরণ:

  • -p 80: কন্টেইনার পোর্ট 80 এক্সপোজ করবে। হোস্টে র‍্যান্ডম পোর্টে অটোমেটিক্যালি ম্যাপ হবে। সঠিক পোর্ট কীভাবে বের করবেন পরে শিখব।
  • -p 80:80: কন্টেইনার পোর্ট 80 কে হোস্ট পোর্ট 80-এ ম্যাপ করবে। কন্টেইনারের ইন্টারনাল IP জানার দরকার নেই। ইন্টারনাল NAT מעורব, Docker ভার্চুয়াল ইন্টারফেসের মাধ্যমে। একাধিক Web সার্ভার চাইলে আলাদা পোর্টে সেটআপ করতে হবে।
docker run -ti -p 22:22 -p 80:80 image-1:latest
FATA[0000] Error response from daemon: Cannot start container 64bd520e2d95a699156f5d40331d1aba972039c3c201a97268d61c6ed17e1619: Bind for 0.0.0.0:80 failed: port is already allocated

অন্যান্য বিবেচনাগুলো: IP ফরোয়ার্ডিং, ব্রিজড নেটওয়ার্ক, পাবলিক/প্রাইভেট নেটওয়ার্ক, সাবনেট রেঞ্জ, ফায়ারওয়াল রুল, লোড ব্যালেন্সিং। ফিলহাল চিন্তা নেই।

পোর্ট এক্সপোজ করার আরেকটি পদ্ধতি Dockerfile-এ আলোচনা করব। এখন শুধু -p অপশন মনে রাখুন।

IP ঠিকানা চেক করা

হোস্ট পোর্ট ফ্রি রাখতে চাইলে hostPort বাদ দিন। সেক্ষেত্রে কন্টেইনারের IP ও Web সার্ভার পোর্ট দিয়ে সরাসরি কানেক্ট করা যাবে। কন্টেইনারের ডিটেইল বের করতে:

docker inspect <container name or ID>

খুব লম্বা ডিটেইলস দেবে, KVM XML কনফিগের মতো, কিন্তু JSON ফরম্যাটে—আধুনিক ও বদসूरत ডেটা ফরম্যাট। পড়া যায় কিন্তু খুব বদসूरत।

শুধু IP ঠিকানা বের করতে:

docker inspect <container name or ID> | grep -i "ipaddr"
"IPAddress": "172.17.0.20",

নতুন কনফিগারেশন টেস্ট করা

নতুন করে ইনস্ট্যান্স লঞ্চ করুন, Apache সেটআপ করে চালু করুন। ব্রাউজার খুলে টেস্ট করুন। কাজ করলে Web সার্ভার ঠিক কনফিগার হয়েছে।

docker run -it -p 80:80 centos:centos7 /bin/bash

চলমান কন্টেইনার চেক করলে পোর্ট ম্যাপিং দেখা যাবে:

# docker ps
CONTAINER ID IMAGE COMMAND
43b179c5aec7 centos:centos7 "/bin/bash"

CREATED STATUS PORTS
2 hours ago Up 2 hours 0.0.0.0:80->80/tcp

NAMES distracted_euclid

ব্রাউজারে দেখবেন: (স্ক্রিনশট)

অপশনাল: ইন্টারনাল IP রেঞ্জ শুধু হোস্টে অ্যাক্সেসIBLE। অন্য মেশিন থেকে অ্যাক্সেস করতে NAT ও IP ফরোয়ার্ডিং লাগবে। নাম দিয়ে অ্যাক্সেস করতে /etc/hosts ও DNS কনফিগার করতে হবে। কন্টেইনারে --add-host="host:IP" ডিরেক্টিভ দিয়ে করা যায়।

একটা নোট: Docker-এর নিজস্ব ইন্টারনাল নেটওয়ার্কিং আছে, VirtualBox ও KVM-এর মতো। বড় /16 নেটওয়ার্ক, 꽤 היי ফ্রিডম। হোস্টে:

# /sbin/ifconfig
docker0: flags=4163 mtu 1500
inet 172.17.42.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::5484:7aff:fefe:9799 prefixlen 64 scopeid 0x20
ether 56:84:7a:fe:97:99 txqueuelen 0 (Ethernet)
RX packets 6199 bytes 333408 (325.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11037 bytes 32736299 (31.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

SSH কাজ করছে কিনা চেক করা

SSH-র জন্যও একই এক্সারসাইজ। পোর্ট 22 এক্সপোজ, একাধিক অপশন। একটু ইন্টারেস্টিং করতে র‍্যান্ডম পোর্ট অ্যাসাইনমেন্ট ট্রাই করি:

docker run -ti -p 20 -p 80 centos:centos7 /bin/bash

docker ps দিয়ে পোর্ট চেক:

0.0.0.0:49176->22/tcp, 0.0.0.0:49177->80/tcp boring_mcclintock

এখন docker0 IP অথবা কন্টেইনার IP দিয়ে কানেক্ট করুন। দুটোই একই ফলাফল দেবে।

ssh 172.17.42.1 -p 49117

যেকোনো পদ্ধতিতে রুট পাসওয়ার্ড মাগবে:

ssh 172.17.0.5
The authenticity of host '172.17.0.5 (172.17.0.5)' can't be established. ECDSA key fingerprint is 00:4b:de:91:60:e5:22:cc:f7:89:01:19:3e:61:cb:ea.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts.
root@172.17.0.5's password:

রুট পাসওয়ার্ড কী?

পাসওয়ার্ড জানি না, তাই ফেইল। কন্টেইনারের ভিতরে passwd দিয়ে রুট পাসওয়ার্ড চেঞ্জ করতে চাইলে কাজ করবে না—passwd ইউটিলিটি ইনস্টলড নেই। RPM গ্র্যাব করে কন্টেইনারে ইনস্টল করা যায়। হোস্টে ডিপেন্ডেন্সি চেক:

rpm -q --whatprovides /etc/passwd
setup-2.8.71-5.el7.noarch

এটা সিকিউরিটি ভালনারেবিলিটি। কন্টেইনার লীন রাখতে চাই। তাই হোস্টের /etc/shadow- থেকে পাসওয়ার্ড হ্যাশ কপি করে কন্টেইনারে দিতে পারি। পরে স্ট্রিমলাইনড পদ্ধতি শিখব।

একটা স্পষ্ট বিষয়: আমরা একই কাজ বারবার করছি। এটা ইফিশিয়েন্ট নয়। তাই কন্টেইনারে কिये চেঞ্জগুলো প্রিজার্ভ করতে হবে। পরবর্তী সেকশন এটাই হ্যান্ডেল করে।

ইমেজ কমিট করা

কন্টেইনারে চেঞ্জ করার পর সেটা কমিট করতে পারেন। অর্থাৎ পরবর্তীতে নতুন কন্টেইনার শুরু করলে স্ক্র্যাচ থেকে সব কিছু রিপিট করতে হবে না—এক্সিস্টিং ওয়ার্ক রিয়ুজ করে টাইম ও ব্যান্ডউইথ বাঁচাবে। কন্টেইনার আইডি বা এলিয়াস দিয়ে কমিট:

docker commit <container name or ID> <new image>

উদাহরণ:

docker commit 43b179c5aec7 myapache3
1ee373ea750434354faeb1cb70b0177b463c51c96c9816dcdf5562b4730dac54

ইমেজ লিস্ট চেক করুন।

Dockerfile

ইমেজ তৈরির আরও স্ট্রিমলাইনড পদ্ধতি: Dockerfile। কম্পাইলেশনের Makefile-এর মতো, Docker ফরম্যাটে। বা RPM specfile। যেকোনো "build" ডিরেক্টরিতে Dockerfile তৈরি করুন। কী কী ঢুকানো যায় এবং কেন Apache+SSH এক্সারসাইজের জন্য দরকার, সেটা শিখব। কমিট করা ইমেজের সাথে কম্বাইন করলে সফ্টওয়্যার ইনস্টলেশন প্রিজার্ভ হয়—ফাস্টার এবং নেটওয়ার্ক ইউটিলিটি বাঁচায়।

আমাদের এক্সারসাইজের জন্য 사용할 Dockerfile:

FROM myhttptest2:latest

EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]

EXPOSE 80

RUN mkdir -p /run/httpd
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

এখানে কী কী?

  • FROM: বেসলাইন repo:tag। আমাদের কেসে কমিট করা ইমেজ যেটা httpd, sshd বাইনারি, SSH কী ইত্যাদি ধারণ করে।
  • EXPOSE 22: কন্টেইনারের ভিতর পোর্ট 22 এক্সপোজ। রানটাইমে -p দিয়ে আরও ম্যাপ করা যাবে। EXPOSE 80 Web সার্ভারের জন্য।
  • CMD ["/usr/sbin/sshd", "-D"]: এক্সিকিউটেবল রান করে আর্গুমেন্টসহ। এতটুকু।
  • RUN mkdir -p /run/httpd: বেস ইমেজের ওপর নতুন লেয়ারে কমান্ড রান করে রেজাল্ট কমিট করে। খুব গুরুত্বপূর্ণ—Apache-র সাথে RUN mkdir না করলে কী হয় পরে আলোচনা করব।
  • CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]: সার্ভার ফোরগ্রাউন্ডে রান। লাস্ট বিট অপশনাল, কিন্তু ফিলহাল এভাবে Apache শুরু করা যাবে।

Dockerfile সিম্পল কিন্তু অত্যন্ত উপকারী। আপনি প্রায় সব কিছু যোগ করতে পারেন। অটোমেশনের ভিত্তি, কন্ডিশনাল লজিক দিয়ে বিবিধ সিনেরিও ও কন্টেইনার স্পান করা যায়।

ইমেজ বিল্ড করা

Dockerfile রেডি হলে ইমেজ বিল্ড। Dockerfile স্ট্রিক্ট কনভেনশন মেনে চলে, Makefile-এর মতো। আলাদা ইমেজ বিল্ড আলাদা সাব-ডিরেক্টরিতে রাখা ভালো। উদাহরণ:

docker build -t test5 .
Sending build context to Docker daemon 41.47 kB
Sending build context to Docker daemon
Step 0 : FROM myapache4:latest
---> 7505c70235e6
Step 1 : EXPOSE 22 80
---> Using cache
---> 58f11217c3e3
Step 2 : CMD /usr/sbin/sshd -D
---> Using cache
---> 628c3d6b5399
Step 3 : RUN mkdir -p /run/httpd
---> Using cache
---> 5fc118f61a4d
Step 4 : CMD /usr/sbin/httpd -D FOREGROUND
---> Using cache
---> d892acd86198
Successfully built d892acd86198

-t রিপোজিটরি নাম, বর্তমান ডিরেক্টরি (.)-তে Dockerfile থেকে। সিম্পল ও এলিগ্যান্ট।

ইমেজ টেস্ট করা

বनানো ইমেজ থেকে নতুন কন্টেইনার চালান। সব ঠিক থাকলে SSH কানেক্টিভিটি ও রানিং Web সার্ভার পাবেন। নেটওয়ার্ক রুলগুলো প্রযোজ্য।

বিকল্প বিল্ড

নিজে করলে অফিসিয়াল Apache বিল্ড ট্রাই করুন। Docker রিপোজিটরিতে ভালো টেমপ্লেট আছে। Apache-র জন্য Dockerfile-এ শুধু এগুলো দরকার:

FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

COPY ইনস্ট্রাকশন

উপরে কী? Dockerfile-এ টেমপ্লেট ডিক্লেয়ারেশন। তারপর COPY ইনস্ট্রাকশন—কারেন্ট ফোল্ডারের public-html ডিরেক্টরি খুঁজে কন্টেইনারে বিল্ড টাইমে কপি করবে। একইভাবে httpd.conf কপি করা যাবে। ডিস্ট্রোর মোতাবিক পাথ ফাইলনেম আলাদা হতে পারে। বিল্ড করে কন্টেইনার চালালে:

docker run -ti -p 22 -p 80 image-1:latest
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.17. Set the 'ServerName' directive globally to suppress this message
[Thu Apr 16 21:08:35.967670 2015] [mpm_event:notice] [pid 1:tid 140302870259584] AH00489: Apache/2.4.12 (Unix) configured -- resuming normal operations
[Thu Apr 16 21:08:35.976879 2015] [core:notice] [pid 1:tid 140302870259584] AH00094: Command line: 'httpd -D FOREGROUND'

কন্টেইনারের সুবিধাগুলো

এই টেকনোলজি ব্যবহার করার অনেক কারণ। ছোট, আইসোলেটেড ইনস্ট্যান্স চালাতে কী লাভ? কার্নেলের নিচে অনেক কিছু ঘটলেও, স্পান করা কন্টেইনারের মেমরি ফুটপ্রিন্ট ছোট। আমাদের কেসে SSH+Apache কন্টেইনার অতিরিক্ত মেমরির ছোট অ অংশ ব্যবহার করে। যেকোনো ভার্চুয়ালাইজেশন টেকনোলজির সাথে তুলনা করুন।

সমালোচনা সম্ভাব্য সমস্যা ও ট্রাবলশুটিং

Apache উদাহরণে ফিরি, এখন শিখবেন কেন অনলাইন টিউটোরিয়ালের অধিকাংশ কপি-পেস্ট করে ভুল ইনফো দেয়। Apache সার্ভার কন্টেইনার লঞ্চের ১-২ সেকেন্ডের ভিতরে ডাই করে যাওয়া সমস্যা। ट्रাবলশুট করতে কন্টেইনারে ঢুকতে হবে। docker exec দিয়ে শেল আট্যাচ করুন:

docker exec -ti boring_mcclintock /bin/bash

লগ পড়ে সমস্যা বের করুন। httpd.conf ঠিক থাকলে /var/log/httpd-এ অ্যাক্সেস ও এরর লগ থাকবে:

[auth_digest:error] [pid 25] (2)No such file or directory: AH01762: Failed to create shared memory segment on file /run/httpd/authdigest_shm.25

সাধারণ সমস্যা: /run/httpd ডিরেক্টরি মিসিং। নাইলে httpd শুরু হয়ে মরবে। একদম সিম্পল, কিন্তু কয়েকজনই এটা মেনশন করে।

আমিও এই সমস্যা ফেস করেছিলাম। অনলাইনে কয়েকটা সাজেশন পেলাম, কোনোটাই ঠিকমতো হেল্প করল না। কিন্তু আমি আলোচনা করব, কীভাবে ইন্টারমিডিয়েট স্টেপস উপকরিত না হলেেও প্রগতি করা যায়।

সাজেশন ১: -D FOREGROUND দিয়ে Apache চালাতে হবে, এবং CMD বদলে ENTRYPOINT ব্যবহার করতে হবে। পার্থক্য সাবটাইল। কিন্তু আমাদের সমস্যা সমাধান করে না।

ENTRYPOINT ["/usr/sbin/httpd"]
CMD ["-D", "FOREGROUND"]

সাজেশন ২: আলাদা স্টার্টআপ স্ক্রিপ্ট ব্যবহার করুন। Dockerfile:

...
EXPOSE 80
COPY ./run-httpd.sh /run-httpd.sh
RUN chmod -v +x /run-httpd.sh
CMD ["/run-httpd.sh"]

স্ক্রিপ্ট কন্টেন্ট:

#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND

প্রায় হয়ে গেলো। পুরনো PID ফাইল রিমুভ, কিন্তু সেগুলো সাধারণত /var/run/httpd-এ থাকে। আর আমরা নিশ্চিত নই সেটা এক্সিস্ট করে।

আইডিয়া: শেল এক্সিকিউশন প্রব্লেম ওয়ার্কঅরাউন্ড। COPY এবং RUN ইনস্ট্রাকশন শিখতে উপকারী, কিন্তু আমাদের ইশ্যু ফিক্স করল না।

বিল্ড আউটপুট দেখুন—ক্যাম বা সফল হলেও রান করলে apachectl Unsupported, স্টার্টআপ স্ক্রিপ্টের সমস্যা রইল। আলাদা টিউটোরিয়ালে ফিক্স করব।

এই আলাদা পদ্ধতিগুলো ট্রাই করা আপনাকে অভ্যাস দেবে। কিন্তু এই টেকনোলজির অপরিপক্বতা ও অসম্পূর্ণ ডকুমেন্টেশন হাইলাইট হয়েছে।

অতিরিক্ত কমান্ডগুলো

কন্টেইনারের সাথে ইন্টারঅ্যাক্ট করার অনেক পথ। নতুন শেল আট্যাচ না করে ডায়রেক্ট কন্টেইনারে কমান্ড চালাতে পারেন:

docker <command> <container name or ID>

উদাহরণ: কন্টেইনার থেকে top আউটপুট:

docker top boring_stallman

অনাবশ্য ইমেজ রিমুভ করে ডিস্ক স্পেস ফรี করতে docker rmi:

# docker rmi -f test7
Untagged: test7:latest
Deleted: d0505b88466a97b73d083434b2dd0e7b59b9a5e8d0438b1bf8c6c
Deleted: 5fc118f61bf856f6f3d90e0e71076b737fa7cc58cd56785ea7904
Deleted: 628c3d6b53992521c9c1fdda4148693347c3d10b1d130f7e091e7
Deleted: 58f11217c3e31206b4e41d07100a797cd4d17e4569b0fdb8b7a18
Deleted: 7505c70235e638c54028ea5b63eba2b691de6bee67c2cb5e2861a
...

-d ফ্ল্যাগ দিয়ে ব্যাকগ্রাউন্ডে কন্টেইনার চালান—শেল প্রম্পট ফিরে আসবে। সিগন্যাল মাস্ক না করলে অকস্মাত ব্রেক করলে কন্টেইনার কিল হয়ে যেতে পারে।

docker run -d -ti -p 80 image-3:latest

ইভেন্ট চেক, ফাইলসিস্টেম চেঞ্জ একজামিন, হিস্টরি চেক—ভার্সন কন্ট্রোল বিল্ট-ইন। এক্সপোর্ট/ইম্পোর্ট টারড ইমেজ রিমোট লোকেশন বা ওয়েবে।

exec এবং attach-এর পার্থক্য

ডকুমেন্টেশনে দেখবেন: চলমান কন্টেইনারে কানেক্ট করার দুটি কমান্ড—exec এবং attach। পার্থক্য কী?

অফিসিয়াল ডকু মতে:

docker exec চলমান কন্টেইনারে নতুন কমান্ড রান করে। কমান্ড টা চলবে যতক্ষণ কন্টেইনারের প্রাইমারি প্রসেস (PID 1) চলছে, এবং কন্টেইনার রিস্টার্ট হলে রিস্টার্ট হবে না।

অন্যদিকে attach:

docker attach চলমান কন্টেইনারে আট্যাচ করতে দেয় ID বা নাম দিয়ে, আউটপুট দেখতে বা ইন্টারঅ্যাক্টিভ কন্ট্রোল করতে। একই প্রসেসে একাধিকবার আট্যাচ করা যায় (স্ক্রিন শেয়ারিং স্টাইল), বা ডেমনাইজড প্রসেসের প্রগ্রেস কুইকলে দেখতে পারেন। CTRL-p CTRL-q দিয়ে ডিট্যাচ (কুইয়েট এক্সিট) বা CTRL-c দিয়ে SIGKILL পাঠাতে পারেন। আট্যাচড স্টেটে মেইন প্রসেস এক্সিট করলে এক্সিট কোড ক্লায়েন্টকে রিটার্ন হবে।

অর্থাৎ attach-এ শেল পাবেন, যা ইচ্ছা করুন। exec-এ ইন্টারঅ্যাকশন না চাইয়া কমান্ড ইস্যু করুন, কিন্তু শেল দিয়ে exec করলে attach-এর মত ফলাফল পাবেন।

start এবং run-এর পার্থক্য

start: স্টপ করা কন্টেইনার রিজিউম করতে। ফ্রেশ ইনস্ট্যান্স শুরু করার জন্য নয়। সেটার জন্য run। শব্দের চয়েন ভালো হয়তো।

build এবং create-এর পার্থক্য

build: Dockerfile থেকে নতুন ইমেজ তৈরি। create: কমান্ড লাইন অপশন ও আর্গুমেন্ট দিয়ে নতুন কন্টেইনার তৈরি। create-এ কন্টেইনার সেটিংস স্পেসিফাই করা যায়—নেটওয়ার্ক কনফিগ, রিসোর্স লিমিটেশন, আউটসাইড থেকে কন্টেইনারকে প্রভাবিত करने वाली সেটিংস। build-এ চেঞ্জস ইমেজের ভিতরে রিফ্লেক্ট হয়, ইনস্ট্যান্স শুরু করলে। আর শুরু মানে run। বুঝলেন?

এটা শুধু শুরু...

আরো লক্ষ লক্ষ কাজ আছে: systemd-ইনাবলড কন্টেইনার, পলিসি, সিকিউরিটি, রিসোর্স কনস্ট্রেইন্ট, প্রক্সি, সিগন্যাল, অন্যান্য নেটওয়ার্ক ও স্টোরেজ অপশন—সুপার-ক্রিটিক্যাল প্রশ্ন: কন্টেইনার মরে যাওয়া সময় ডেটা নষ্ট না হয় সেজন্য ডেটা ভলিউম কীভাবে মাউন্ট করবেন, পিউর LXC কমান্ড, আরো অনেক কিছু। আমরা কেবল সতহ স্পর্শ করলাম। কিন্তু এখন জানি কী করতে হবে। ধীরে ধীরে পৌঁছাব।

আরো পড়ুন

কয়েক ঘন্টা বরাদ্দ করে নিচের সবগুলো ডিটেইলস পড়ুন। তারপর প্র্যাকটিস। একমাত্র পথ সম্পূর্ণ বোঝার।

  • আমার পুরো ভার্চুয়ালাইজেশন সেকশন
  • Dockerizing an SSH Daemon Service
  • Differences between save and export in Docker
  • Docker Explained: Using Dockerfiles to Automate Building of Images

উপসংহার

আজকের টিউটোরিয়াল শেষ। উপকারী লাগলে খুশি। সংক্ষেপে: Docker-র সাথে শুরু, নতুন ইমেজ পুল, বেসিক কন্টেইনার রান, SSH ও Apache সার্ভিস যোগ, চেঞ্জ কমিট, ইনকামিং পোর্ট এক্সপোজ, Dockerfile দিয়ে নতুন ইমেজ বিল্ড, প্রচুর ট্রাবলশুটিং, অতিরিক্ত কমান্ড, আরো অনেক কিছু। ইভেন্টফুল ও কালারফুল।

ভবিষ্যতে এখান থেকে অনেক বেশি এক্সপ্যান্ড করব—supervisord-এর মতো হেল্পার টেকনোলজি, ফাইলসিস্টেম মাউন্ট, অ্যাডমিনিস্ট্রেশন ও অর্কেস্ট্রেশন, আরো অনেক কুল জিনিস। Docker খুব সুন্দর কনসেপ্ট, সঠিকভাবে ব্যবহার করলে আপনার ভার্চুয়াল ওয়ার্ল্ড সহজ ও এলিগ্যান্ট করবে। প্রথম কয়েক ধাপ রাফ, কিন্তু এই গাইড আপনাকে সঠিক করমা দিয়ে খুশি ও আত্মবিশ্বাসের সাথে এগিয়ে যেতে সাহায্য করবে। কোনো রিকোয়েস্ট বা কাঙ্ক্ষা হলে পিং করুন। টেকনোলজি-রিলেটেড, অবশ্যই। কাজ শেষ।

P.S. আর্টিকেলটা পছন্দ হলে Dedoimedo-কে কিছু প্রেম দিন! চিয়ার্স।

  1. ফায়ারফক্স ৪ আয়ত্ত করা: সুবিধাজনক ব্রাউজিং-এর জন্য সহজ গাইড

  2. KVM ভার্চুয়ালাইজেশন মাস্টার করুন: কernel-বেজড ভার্চুয়াল মেশিনের কম্প্রিহেনসিভ গাইড

  3. XenServer & XenCenter 리뷰: 랩톱에서의 원활한 설치

  4. উইন্ডোজ BSOD ব্যাখ্যা: ডায়গনোসিস ও ফিক্সের সম্পূর্ণ গাইড