Docker Compose stop বনাম down: কোনটি কী মুছে দেয়
stop কনটেইনার ও writable layer রেখে শুধু বন্ধ করে; down কনটেইনার ও project network মুছে দেয়। named volume মুছতে শুধু volumes flag প্রয়োজন।
সংক্ষিপ্ত উত্তর
docker compose stop container-গুলো বন্ধ করে এবং disk-এ রেখে দেয়। docker compose down container-গুলো বন্ধ করার পর সেগুলো এবং এই project-এর জন্য Compose তৈরি করা network মুছে দেয়। কোনো command-ই named volume-এ প্রভাব ফেলে না। -v যোগ করলে, যেমন docker compose down -v-এ, Compose file-এর volumes section-এ ঘোষিত এবং এই project-এর অন্তর্ভুক্ত non-external named volume মুছে যায়। down যে জিনিসটি সত্যিই মুছে ফেলে, তা হলো কোনো container তার নিজস্ব writable layer-এ, volume-এর বাইরে, যা লিখেছে।
এটাই পুরো পার্থক্য এক paragraph-এ। এই guide-এর বাকি অংশে একটি Postgres volume ব্যবহার করে দেখানো হবে যে সেটি down চালানোর পরও টিকে থাকে এবং down -v চালালে মুছে যায়। এছাড়া, কোন দুটি ক্ষেত্রে --force-recreate প্রয়োজন হয়, তা ব্যাখ্যা করা হবে।
docker compose stop: কনটেইনার বন্ধ করার পরও থেকে যায়
stop প্রতিটি কনটেইনারের প্রধান প্রসেসে কনটেইনারে কনফিগার করা stop signal পাঠায়। ডিফল্ট signal হলো SIGTERM। এরপর এটি অপেক্ষা করে এবং প্রসেসটি চালু থাকলে SIGKILL পাঠায়। ডিফল্ট অপেক্ষার সময় 10 সেকেন্ড। -t এই সময় পরিবর্তন করে। কোনো কিছু মুছে ফেলা হয় না। কনটেইনার তার ID, writable layer এবং log ধরে রাখে।
docker compose stop
docker compose ps -adocker compose ps একা ব্যবহার করলে শুধু চলমান কনটেইনার দেখায়। তাই stop-এর পরে এটি একটি খালি table দেখায় এবং মনে হয় কনটেইনারগুলো মুছে গেছে। ps -a বন্ধ থাকা কনটেইনারও অন্তর্ভুক্ত করে। সেখানে প্রতিটি service-এর পাশে Exited status এবং প্রসেসটি ফেরত দেওয়া exit code দেখা যায়। স্বাভাবিকভাবে বন্ধ হলে প্রায়ই Exited (0) দেখা যায়, তবে সব সময় নয়। কিছু server graceful shutdown শেষ করার পর stop signal আবার raise করে। ফলে প্রসেসটি ওই signal-এর কারণে শেষ হয়। Uvicorn ঠিক এভাবেই কাজ করে। তাই সুশৃঙ্খলভাবে বন্ধ হওয়ার পরও non-zero code থাকতে পারে। non-zero code প্রসেস ব্যর্থ হওয়া বা timeout-এর পরে প্রসেসটি বন্ধ করে দেওয়াও নির্দেশ করতে পারে। docker compose start দিয়ে কনটেইনারগুলো আবার চালু করুন। এটি ঠিক একই কনটেইনার পুনরায় ব্যবহার করে।
কনটেইনারগুলো এখনও বিদ্যমান থাকায় volume-এর বাইরে কনটেইনারের ভেতরে লেখা যেকোনো কিছু সেখানেই থাকে। এর মধ্যে docker compose exec দিয়ে হাতে ইনস্টল করা package এবং কনটেইনারের ভেতরে সম্পাদনা করা config file-ও রয়েছে। Debug করার সময় stop পছন্দ করার এটি একটি বাস্তব কারণ। একই state-এ আবার শুরু করা যায়।
docker compose down: container এবং network অপসারণ করা হয়
down container-গুলো বন্ধ করে। এরপর সেগুলো এবং project-এর জন্য Compose তৈরি করা default network অপসারণ করে। Docker documentation-এ এটিকে container বন্ধ করা এবং up তৈরি করা container, network, volume ও image অপসারণ হিসেবে বর্ণনা করা হয়েছে। তবে -v এবং --rmi দিয়ে অনুরোধ করলেই কেবল volume ও image অপসারণের অংশগুলো কার্যকর হয়।
docker compose down
docker compose ps -a
docker network lsdown চালানোর পরে project-এর জন্য ps -a কোনো output দেখায় না এবং <project>_default network আর থাকে না। আপনি name: Compose file-এ সেট না করলে, COMPOSE_PROJECT_NAME সেট না করলে, অথবা -p pass না করলে project name project directory-এর নাম থেকে নেওয়া হয়। কোনো container-এর writable layer-এর ভেতরে করা প্রতিটি পরিবর্তন এখন আর পুনরুদ্ধার করা যাবে না। তাই down-কে এমন একটি command হিসেবে বিবেচনা করুন, যা container মুছে ফেলে এবং volume-এ রাখা data সংরক্ষণ করে।
বর্তমান directory বা তার parent directory-গুলোতে Compose configuration file খুঁজে না পেলে এবং -f বা COMPOSE_FILE দিয়ে কোনো file সরবরাহ না করলে no configuration file provided: not found দেখায়। কোন project বোঝানো হয়েছে তা Compose জানে না। তাই এটি কাজটি প্রত্যাখ্যান করে। আপনি project folder-এ না থাকলে docker compose -f /srv/myapp/compose.yaml down ব্যবহার করুন।
docker compose down কি আমার volume মুছে দেয়?
না। শীর্ষ-স্তরের volumes key-এর অধীনে ঘোষিত named volume down-এর পরেও থাকে এবং যে container-এ এটি সংযুক্ত ছিল, সেই container মুছে গেলেও থাকে। এই command নিয়ে এটাই সবচেয়ে প্রচলিত আশঙ্কা। Compose v5.7.0 down -v পরিবর্তন করেছে: এখন এটি অন্য project-এর অধীন named volume অথবা Compose-এর বাইরে তৈরি volume এড়িয়ে যায় এবং একটি warning দেখায়।
পরীক্ষা করার জন্য একটি stack সেট আপ করুন। খালি directory `voltest-এ compose.yaml` নামে এই বিষয়বস্তু রাখুন।
services:
db:
image: postgres:16.4
restart: unless-stopped
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:এটি চালু করুন এবং পরে শনাক্ত করতে পারবেন এমন একটি row লিখুন।
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "create table marker (note text);"
docker compose exec -T db psql -U postgres -c "insert into marker values ('survived');"এখন container মুছে দিন এবং volume পরীক্ষা করুন।
docker compose down
docker volume lsআউটপুটে এখনও voltest_pgdata তালিকাভুক্ত থাকে। container মুছে গেছে, কিন্তু data মুছে যায়নি। stack আবার চালু করে row-টি পড়ুন।
docker compose up -d
sleep 10
docker compose exec -T db psql -U postgres -c "select * from marker;"আপনি survived-সহ একটি row পাবেন। নতুন container-টি আলাদা ID-যুক্ত একটি ভিন্ন container, তবে এটি একই volume-এর সঙ্গে সংযুক্ত। আরও বিস্তৃত ধারণার জন্য Compose-এর মৌলিক বিষয়ের নির্দেশিকা-তে named volume এবং bind mount-এর তুলনা, এবং host-এ প্রতিটি volume আসলে কোথায় থাকে, তা ব্যাখ্যা করা হয়েছে।
down -v ঠিক কী ধ্বংস করে
-v (দীর্ঘ রূপ --volumes) Compose file-এর volumes section-এ ঘোষিত এবং এই project-এর অন্তর্ভুক্ত non-external named volume সরিয়ে দেয়। এছাড়া container-গুলোর সঙ্গে সংযুক্ত anonymous volume-ও সরিয়ে দেয়। Compose v5.7.0-এ অন্য project-এর ownership label-যুক্ত অথবা কোনো project label না থাকা named volume warning দেখিয়ে এড়িয়ে যায়। এর ownership পরীক্ষা করা না গেলে command ব্যর্থ হয় এবং volume রেখে দেয়। এটি একই stack-এর ওপর চালান।
docker compose down -v
docker volume lsvoltest_pgdata আর তালিকাভুক্ত নেই। আবার stack চালু করুন। তখন Postgres entrypoint একটি খালি data directory দেখতে পায় এবং নতুন cluster initialises করে। Container log-এ বিষয়টি স্পষ্ট ভাষায় লেখা থাকে।
The files belonging to this database system will be owned by user "postgres".
PostgreSQL init process complete; ready for start up.কয়েক মাস ধরে চলা stack-এ এই block দেখা মানে Postgres একটি খালি data directory initialise করছে। আপনার marker table চলে গেছে। ফিরে পাওয়ার একমাত্র উপায় হলো backup।
-v কিছু storage কখনো সরায় না। Bind mount হলো host path। তাই Docker শুধু এটি unmount করে এবং আপনার file যেখানে ছিল সেখানেই থাকে। external: true দিয়ে চিহ্নিত volume এই project-এর বাইরের কোনো কিছুর অন্তর্ভুক্ত হিসেবে ঘোষিত। Compose এটি কখনো সরায় না। down -v চালানোর আগে কোনো named volume Compose file থেকে মুছে ফেললে সেটি আর declared থাকে না। তাই Compose সেটি সরানোর কথা জানতে পারে না। কোনো container আর সেটি reference না করলে volume-টি docker volume prune -a-এর জন্য orphan হিসেবে পড়ে থাকে।
Refactor করার সময় শেষের ঘটনাটি প্রায়ই সমস্যা তৈরি করে। File থেকে কোনো service এবং তার volume সরিয়ে down -v চালালে volume-টি থেকে যায়, কারণ file-এ আর সেটির উল্লেখ নেই। File সম্পাদনা করার আগে down -v চালান, পরে নয়।
যখন সত্যিই --force-recreate প্রয়োজন
docker compose up -d প্রতিবার সবকিছু নতুন করে তৈরি করে না। Compose প্রতিটি service-এর resolved configuration-এর একটি hash container-এর label হিসেবে সংরক্ষণ করে। Compose v5.7.0-এ configuration hash, image ID এবং image-volume digest একই থাকলে, প্রত্যাশিত network connection ও named volume mount উপস্থিত থাকলে, এবং কোনো namespace- বা volume-sharing parent নতুন করে তৈরি না হলে running container অপরিবর্তিত থাকে। তখন Container voltest-db-1 Running-এর পরিবর্তে Recreated পাওয়া যায়। প্রায় সব ক্ষেত্রেই এটিই প্রত্যাশিত আচরণ, কারণ এর ফলে up -d বারবার নিরাপদে চালানো যায়।
এ কারণেই কিছু সম্পাদনার পরও কোনো পরিবর্তন দেখা যায় না। Compose সংশ্লিষ্ট ফাইলের বিষয়বস্তু নয়, resolved service definition-এর hash তৈরি করে। Container-এ mounted কোনো config file শুরুতে একবার পড়া হলে, সেটি সম্পাদনা করলেও recreate শুরু হবে না, কারণ mount path পরিবর্তিত হয়নি। Service boot-এর সময় পড়া মানগুলো দিয়েই চলতে থাকবে।
docker compose up -d --force-recreateএটি প্রতিটি container বন্ধ করে সরিয়ে ফেলে এবং একই definition থেকে নতুন container তৈরি করে। Mounted config file সম্পাদনা করার পরে এবং কোনো container এমন অবস্থায় চলে গেলে যার কারণ ব্যাখ্যা করা যাচ্ছে না, তখন এটি ব্যবহার করুন। Volume অপরিবর্তিত থাকে, তাই force recreate করলেও database অক্ষত থাকে। একই tag-এ থাকা নতুন image ব্যবহার করতে pull-ও প্রয়োজন।
docker compose pull
docker compose up -dpull নতুন image ID সংগ্রহ করে, এবং এরপর up -d running container-এর image ID-এর সঙ্গে ভিন্নতা শনাক্ত করে নিজে থেকেই container recreate করে। pull ছাড়া --force-recreate যোগ করলে একই পুরোনো image থেকে নতুন container তৈরি হবে। তাই “আমি force recreate করেছি, কিন্তু এটি এখনও পুরোনো version” — এই অভিযোগ এত সাধারণ।
docker compose restart এর কোনোটিই করে না। এটি configuration-এ পরিবর্তন প্রয়োগ না করে বিদ্যমান container restart করে। তাই পরিবর্তিত environment variable বা port mapping কার্যকর হবে না। ফাইল সম্পাদনা করে থাকলে up -d ব্যবহার করুন।
মনে রাখার মানসিক মডেল
Container প্রতিস্থাপনযোগ্য। একটি container হলো একটি process এবং তার সঙ্গে যুক্ত একটি পাতলা writable layer। Compose file ও image থেকে নতুন container তৈরি করতে পারে। Volume প্রতিস্থাপনযোগ্য নয়। কারণ এতে state-এর একমাত্র কপি থাকে, যা repository-র কোনো file পুনরায় তৈরি করতে পারে না।
প্রতিটি Compose verb এই বিভাজনের সঙ্গে সামঞ্জস্যপূর্ণ। stop এবং start container অক্ষত রাখে। down এবং up container প্রতিস্থাপন করে, কিন্তু volume অক্ষত রাখে। down -v হলো state সরিয়ে ফেলার একমাত্র নিয়মিত command। তাই এতে একটি explicit flag প্রয়োজন। কোনো বাস্তব সিস্টেমে এটি চালানোর আগে নিশ্চিত করুন যে আপনার একটি backup আছে এবং সেটি অন্তত একবার restore করেছেন।
Secrets-এর ক্ষেত্রেও একই যুক্তি প্রযোজ্য। POSTGRES_PASSWORD-এর মাধ্যমে সেট করা password database প্রথমবার initialize হওয়ার সময় শুধু database password নির্ধারণ করতে ব্যবহৃত হয়। তাই environment file-এ password পরিবর্তন করে up -d চালালেও stored password পরিবর্তিত হয় না। Container নতুন, কিন্তু volume পুরোনো। পুরোনো volume-এ এখনও পুরোনো password সংরক্ষিত থাকে। Compose কীভাবে env file এবং secret resolve করে ব্যাখ্যা করে, একই variable দুবার সেট হলে কোন layer প্রাধান্য পায়।
ব্যর্থতার ধরন এবং যে বার্তাগুলো দেখবেন
no configuration file provided: not found বোঝায়, Compose তার বর্তমান directory এবং parent directory অনুসন্ধান করে কোনো configuration file খুঁজে পায়নি; একই বিষয় -f বা COMPOSE_FILE-এর ক্ষেত্রেও প্রযোজ্য। সম্পূর্ণ path দিয়ে -f ব্যবহার করুন।
Compose v5.7.0-এ down-এর ওপর Network voltest_default Resource is still in use দেখালে বোঝায়, কিছু container এখনও project network-এর সঙ্গে সংযুক্ত আছে। সাধারণত এগুলো এই project-এর বাইরে docker run --network দিয়ে হাতে শুরু করা container। ওই container-গুলো সরিয়ে আবার down চালান।
কোনো service-এর নাম পরিবর্তন বা service মুছে ফেলার পরে Found orphan containers (voltest-old-1) for this project দেখা যায়। বর্তমান Compose নামগুলো সরাসরি এবং comma দিয়ে আলাদা করে তালিকাভুক্ত করে। পুরোনো Compose v2 release-গুলো একই warning দেখায়, তবে নামগুলো square bracket-এর মধ্যে থাকে, যেমন ([voltest-old-1])। পুরোনো container-এ এখনও project label থাকে। docker compose down --remove-orphans এগুলো সরিয়ে দেয়।
ম্যানুয়াল docker volume rm-এ Error response from daemon: remove voltest_pgdata: volume is in use দেখালে বোঝায়, কোনো container এখনও volume-টি reference করছে। থেমে থাকা container-ও এর অন্তর্ভুক্ত। প্রথমে docker compose down চালিয়ে volume সরান, অথবা সরাসরি down -v ব্যবহার করুন। বড় project-এ একটি বহু-service Compose stack দেখায়, একটি project-এ কতগুলো volume জমতে পারে।
FAQ
docker compose down কি আমার database মুছে ফেলে?
Database যদি named volume বা bind mount-এ থাকে, তাহলে না। down container এবং project network সরিয়ে দেয়, কিন্তু volume disk-এ তার data অক্ষত অবস্থায় থেকে যায়। পরবর্তী docker compose up -d একই volume-এ একটি নতুন container সংযুক্ত করে, এবং data তখনও পাওয়া যায়। docker compose down -v Compose file-এর volumes section-এ ঘোষিত এবং এই project-এর অন্তর্ভুক্ত non-external named volume সরিয়ে দেয়।
যে container-টি পরে আবার ব্যবহার করতে চাই, তার ক্ষেত্রে stop এবং down-এর পার্থক্য কী?
stop container রেখে দেয়। তাই docker compose start একই writable layer-সহ একই container-এ ফিরিয়ে নিয়ে যায়। Container-এর ভেতরে হাতে install বা edit করা সবকিছু তখনও থাকে। down container মুছে দেয়। তাই পরবর্তী up -d image থেকে একটি নতুন container তৈরি করে, এবং হাতে করা পরিবর্তনগুলো হারিয়ে যায়। Debugging করার সময় stop ব্যবহার করুন।
একটি Compose project যে সবকিছু তৈরি করেছে, সেগুলো কীভাবে সরাব?
docker compose down -v --rmi all --remove-orphans container, project network, file-এ ঘোষিত এবং এই project-এর অন্তর্ভুক্ত non-external named volume, service-গুলো যে image ব্যবহার করেছে, এবং project-এর orphan container সরিয়ে দেয়। এটি bind mount বা external: true হিসেবে চিহ্নিত volume-এ কোনো পরিবর্তন করে না। চালানোর আগে docker volume ls ব্যবহার করে কী হারাতে পারেন তা পরীক্ষা করুন।
Mounted config file-এ করা পরিবর্তন আমার container কেন উপেক্ষা করছে?
Compose resolved service definition-এর hash তুলনা করে container পুনরায় তৈরি করবে কি না তা নির্ধারণ করে। এই hash-এ mounted file-এর contents অন্তর্ভুক্ত থাকে না। Path পরিবর্তিত হয়নি, তাই Compose container চালু রাখে এবং startup-এর সময় পড়া value-গুলোই ব্যবহার করে। File-টি আবার পড়ে একটি নতুন container তৈরি করতে docker compose up -d --force-recreate চালান।
পরিবর্তন করার পরে আমার নতুন POSTGRES_PASSWORD কেন কাজ করছে না?
Postgres image খালি data directory initialise করার সময় database password সেট করতে শুধু POSTGRES_PASSWORD ব্যবহার করে। আপনার volume-এ ইতিমধ্যে initialised cluster রয়েছে। তাই variable-টি উপেক্ষিত হয় এবং পুরোনো password কার্যকর থাকে। নতুন password দিয়ে সংযোগ করলে password authentication failed for user "postgres" পাবেন। চলমান database-এর ভেতরে ALTER USER ব্যবহার করে password পরিবর্তন করুন। অথবা data হারানোর ঝুঁকি মেনে docker compose down -v দিয়ে নতুন করে শুরু করুন।