Docker Compose: একটি ফাইলে multi-container অ্যাপ চালান

লম্বা docker run কমান্ড টাইপ করা ছাড়ুন। একটি compose.yaml পুরো stack চালু করে, একটি কমান্ডে বন্ধ হয়। পরীক্ষিত উদাহরণসহ।

web container ও Redis container জোড়া একটি compose ফাইল

আসল অ্যাপ প্রায়ই একাধিক process: web server, database, cache। প্রতিটি লম্বা docker run কমান্ডে চালানো ধীর ও ভুলপ্রবণ। Docker Compose পুরো stack একটি ফাইলে বর্ণনা করতে দেয় এবং একটি কমান্ডে চালু, বন্ধ ও পুনর্নির্মাণ করে। ধরে নেওয়া হচ্ছে আপনি Docker-এর গোড়া (image, container, Dockerfile) জানেন। নিচের উদাহরণ প্রকাশের আগে Docker Compose v2-এ চালানো হয়েছে।

ধারণা

আপনি একটি compose.yaml লেখেন যাতে service (container), তাদের image, port, volume ও সেটিং থাকে। Compose একটি ব্যক্তিগত network বানায় যাতে service-গুলো একে অপরকে service-এর নাম দিয়ে পায়, এবং সব একসঙ্গে চালায়।

একটি কাজের উদাহরণ

একটি web server (nginx) ও একটি Redis cache। compose.yaml নামে সংরক্ষণ করুন, আর পাশে site folder-এ যেকোনো index.html রাখুন:

services:
  web:
    image: nginx:alpine
    ports:
      - "8099:80"
    volumes:
      - ./site:/usr/share/nginx/html:ro
    depends_on:
      cache:
        condition: service_healthy
    restart: unless-stopped

  cache:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - cache-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

volumes:
  cache-data:

চালান

$ docker compose up -d
 Container demo-cache-1  Started
 Container demo-cache-1  Healthy
 Container demo-web-1    Started

$ docker compose ps
SERVICE   IMAGE            STATUS                    PORTS
cache     redis:7-alpine   Up 13 seconds (healthy)   6379/tcp
web       nginx:alpine     Up 6 seconds              0.0.0.0:8099->80/tcp

$ curl localhost:8099
<h1>Hello from Compose</h1>

$ docker compose exec cache redis-cli set greeting hello
OK

$ docker compose down          # removes containers and network, keeps the volume
$ docker compose up -d
$ docker compose exec cache redis-cli get greeting
hello

$ docker compose down -v       # also removes the volume (data is gone)

(Container-এর নাম আপনার folder বা project-এর নামের ওপর নির্ভর করে, আর image-এর আকার ও সময় আলাদা হবে।)

প্রতিটি অংশ কী করে

  • services: প্রতিটি key (web, cache) একটি container। এর নামই Compose network-এ এর hostname, তাই web অ্যাপ IP ছাড়া cache:6379 দিয়ে Redis-এ পৌঁছায়।
  • image: কোন image চলবে। নিজের Dockerfile থেকে বানাতে build: . দিন।
  • ports: "8099:80": host-এর 8099 port container-এর 80-তে যায়। শুধু দরকারি port খুলুন। Redis-এ ports নেই, তাই এটি শুধু অন্য service-এর নাগালে, যা নিরাপদতর।
  • volumes: ./site:/usr/share/nginx/html:ro স্থানীয় folder-এর bind mount, read-only (:ro)। cache-data:/data Docker-পরিচালিত named volume, যা Redis-এর data container-এর বাইরে রাখে।
  • healthcheck: Compose বারবার যে কমান্ড চালিয়ে বোঝে service সুস্থ কি না।
  • depends_on ও condition: service_healthy: cache সুস্থ হলে তবেই web চালু করুন। সাধারণ depends_on শুধু container চালু হওয়া পর্যন্ত অপেক্ষা করে, প্রস্তুত হওয়া পর্যন্ত নয়। এই ফারাকই অনেক "চালুর সময় connection refused" bug-এর কারণ।
  • restart: unless-stopped: crash বা server reboot-এর পর container আবার চালায়, যদি না আপনি নিজে থামান।

প্রতিদিনের কমান্ড

কমান্ড কাজ
docker compose up -d stack ব্যাকগ্রাউন্ডে চালু
docker compose ps অবস্থা দেখা
docker compose logs -f web এক service-এর log অনুসরণ
docker compose exec cache sh চলমান service-এর ভেতরে shell
docker compose up -d --build কোড বদলের পর image পুনর্নির্মাণ
docker compose down container ও network বন্ধ ও মোছা, volume থাকে
docker compose down -v volume-ও মোছে (data যায়)
docker compose config ফাইল যাচাই ও চূড়ান্ত রূপ দেখা

Data ও volume: গুরুত্বপূর্ণ শিক্ষা

উপরের চালানোয় আমরা একটি key রেখে down ও up করলাম, আর key তখনও ছিল, কারণ তা named volume-এ। Container ফেলনা; data থাকে volume-এ। down -v volume মুছে দেয়, তাই data সত্যিই মুছতে চাইলেই ব্যবহার করুন। Volume ছাড়া container-এ database রাখবেন না।

কনফিগারেশন ও secret

  • সেটিং compose.yaml-এর পাশে .env ফাইলে রাখুন এবং ফাইলে ${VARIABLE} হিসেবে ব্যবহার করুন। আসল পাসওয়ার্ডসহ .env কখনো Git-এ commit করবেন না; .gitignore-এ রাখুন এবং .env.example commit করুন।
  • compose.yaml-এ পাসওয়ার্ড সরাসরি লিখবেন না।
  • image-এর সংস্করণ স্থির করুন (latest নয়, redis:7-alpine), যাতে হালনাগাদ আপনাকে চমকে না দেয়।

সাধারণ সমস্যা

  • Port আগে থেকেই ব্যবহৃত: ports-এর বাঁ দিক বদলান ("8100:80")।
  • এক service অন্যটিতে পৌঁছাতে পারছে না: localhost নয়, service-এর নাম ব্যবহার করুন। Container-এর ভেতরে localhost মানে সেই container নিজে।
  • কোড বদল দেখা যাচ্ছে না: --build দিয়ে পুনর্নির্মাণ করুন, বা development-এ bind mount ব্যবহার করুন।
  • Database প্রস্তুত হওয়ার আগে চালু: condition: service_healthy সহ health check ব্যবহার করুন, এবং অ্যাপে connection আবার চেষ্টার ব্যবস্থা রাখুন।
  • down -v-এর পর data হারানো: ওই flag volume মোছে। আগে backup নিন।

Production-এ Compose?

Compose স্থানীয় development, test ও ছোট একক-server deployment-এর জন্য চমৎকার। এটি container অনেক মেশিনে ছড়ায় না বা server জুড়ে নিজে সারায় না। তার জন্য Kubernetes-এর মতো orchestrator ব্যবহার হয়। একটি ছোট server-এ restart: unless-stopped, volume ও backup সহ Compose যুক্তিসংগত পছন্দ।

মূল কথা: stack একবার compose.yaml-এ বর্ণনা করুন, networking-এ service-এর নাম ব্যবহার করুন, চালুর ক্রমে health check দিন, data volume-এ রাখুন, এবং secret ফাইলের বাইরে রাখুন।


Linux ও DevOps সিরিজ, পর্ব ৩ (প্রতিদিনের পরিচালনা): 1 নম্বর (মোট 5)।

আরও পড়ুন

Python দিয়ে এলোমেলো CSV পরিষ্কার: নাম, তারিখ, ফোন ও ডুপ্লিকেট

আসল data এলোমেলো। standard library দিয়ে contacts পরিষ্কার করা, প্রতিটি বাতিল row ব্যাখ্যা করা ও test-সহ একটি script বানান।

প্রজেক্ট•৫ মিনিটে পড়া