Docker Compose: حقیقی سرورز کے لیے ضروری commands
Docker Compose V2 کے روزمرہ commands ایک جگہ: lifecycle، تبدیلیاں نافذ کرنا، logs، shells، networks، volumes اور محفوظ cleanup، ساتھ اہم version gotcha۔
وہ Compose کمانڈز جو آپ حقیقتاً استعمال کرتے ہیں
Docker Compose درجنوں subcommands فراہم کرتا ہے۔ سرور پر روزمرہ کام کے لیے تقریباً ایک درجن کمانڈز کافی ہوتی ہیں۔ یہ صفحہ ان کمانڈز کو آپ کے کام کے مطابق گروپ کرتا ہے، ہر کمانڈ کی ایک واضح وجہ بتاتا ہے، اور جہاں کسی کمانڈ میں کوئی اہم پیچیدگی ہو وہاں تفصیلی وضاحت کی طرف رہنمائی کرتا ہے۔
یہاں ہر جگہ Compose V2 یا V5 استعمال کیا گیا ہے: docker compose کے درمیان space کے ساتھ، نہ کہ پرانی docker-compose script۔ دونوں Go plugins ہیں؛ Linux پر Compose plugin، Docker Engine سے الگ install کیا جاتا ہے۔ Ubuntu 24.04 LTS اب بھی اپنے universe repository میں legacy Python V1 tool کو docker-compose version 1.29.2-6ubuntu1 کے طور پر فراہم کرتا ہے۔ docker compose version سے تصدیق کریں۔ اگر کمانڈ دستیاب نہ ہو تو Docker کی repository configure کریں اور docker-compose-plugin package install کریں۔
ذیل کی ہر کمانڈ اس directory سے چلتی ہے جس میں آپ کی compose.yaml موجود ہو؛ Compose، override نہ کیے جانے کی صورت میں، اسی directory کے نام کو default project name کے طور پر استعمال کرتا ہے۔ -f یا COMPOSE_FILE کے بغیر Compose، configuration file کے لیے working directory اور اس کی parent directories میں تلاش کرتا ہے۔ اس لیے ایک level اوپر سے چلانے پر آپ کا stack صرف اسی صورت میں ملے گا جب اس کی file اب بھی search path میں موجود ہو۔ اگر file format آپ کے لیے نیا ہے تو VPS پر پہلی Compose file سے شروع کریں، پھر کمانڈز کے لیے یہاں واپس آئیں۔
لائف سائیکل: وہ چار کمانڈز جو آپ چلاتے ہیں، اور وہ ایک جو containers کو حذف کرتی ہے
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d network بناتا ہے، containers بناتا ہے، انہیں شروع کرتا ہے، اور واپس آ جاتا ہے۔ containers شروع کرنے کے بعد یہ application کے ready ہونے کا انتظار کیے بغیر واپس آ جاتا ہے۔ اسی لیے اس کے بعد چلنے والا deploy script، جس میں اکثر curl probe شامل ہوتا ہے، پہلی کوشش میں ناکام ہو جاتا ہے۔ up -d --wait healthchecks والی services کے healthy ہونے اور healthcheck کے بغیر services کے running ہونے کا انتظار کرتا ہے؛ unhealthy service یا expired --wait-timeout کی صورت میں exit status non-zero ہوتا ہے۔ یہ flag صرف اتنا ہی مؤثر ہے جتنا اس کے پیچھے موجود check۔ اس لیے automation میں اس پر انحصار کرنے سے پہلے ایسا healthcheck لکھیں جس پر Compose اعتماد کر سکے۔
stop containers کو روک دیتا ہے لیکن انہیں برقرار رکھتا ہے، اس لیے start وہی containers اسی writable layer کے ساتھ دوبارہ شروع کرتا ہے۔ down containers کو روکتا ہے اور پھر containers اور project network کو حذف کر دیتا ہے۔ container کے اندر volume کے باہر لکھی گئی ہر چیز containers کے ساتھ حذف ہو جاتی ہے۔ Compose میں یہ سب سے مہنگی غلط فہمی ہے، اور down اور stop کے درمیان مکمل فرق بتاتا ہے کہ اس کا نقصان کہاں ہوتا ہے۔
restart reload نہیں ہے۔ یہ اسی container کو اس کی موجودہ configuration کے ساتھ روکتا اور دوبارہ شروع کرتا ہے۔ اس لیے تبدیل کیا گیا environment variable، نیا image tag یا ترمیم شدہ port mapping بالکل مؤثر نہیں ہوتی۔ file change نافذ کرنے کے لیے آپ دوبارہ up -d چلاتے ہیں۔ Compose ہر service کا اس کے running container کے ساتھ موازنہ کرتا ہے اور جن services کی configuration یا image تبدیل ہوئی ہو، ان کے containers دوبارہ بناتا ہے۔
تبدیلی نافذ کرنا: دوبارہ بنانا، pull کرنا، یا rebuild کرنا
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d چلنے والے containers کو دوبارہ استعمال کرتا ہے، بشرطیکہ ان کی configuration اور image میں تبدیلی نہ ہوئی ہو؛ image pulls اور builds، service کی pull policy کے مطابق ہوتے ہیں۔ --force-recreate اس موازنے کو نظرانداز کرتا ہے اور configuration یکساں ہونے کے باوجود ہر container کو تبدیل کر دیتا ہے، اس لیے container کے اندر موجود غیر معمولی state صاف کرنے کا یہ تیز ترین طریقہ ہے۔
واضح image update routine میں دو commands استعمال ہوتی ہیں، کیونکہ دونوں مختلف کام کرتی ہیں۔ pull file میں درج ہر tag کی موجودہ image download کرتا ہے۔ اس کے بعد up -d دیکھتا ہے کہ service کی image ID اس کے چلتے ہوئے container سے مطابقت نہیں رکھتی، اور container کو دوبارہ بناتا ہے۔ default missing pull policy کے ساتھ cached tags دوبارہ استعمال ہوتے ہیں، سوائے latest کے، جسے ہمیشہ pull کیا جاتا ہے۔ اس کے برعکس multi-service stack میں یہ خطرہ پیدا ہوتا ہے کہ ہر service کے لیے بیک وقت latest pull کرنے سے وہ app بھی خراب ہو سکتی ہے جو دس سیکنڈ پہلے تک درست چل رہی تھی۔ اسی لیے self-hosted AFFiNE workspace اس کے بجائے application اور migration image کو ایک ہی digest پر pin کرنے کی تجویز دیتا ہے۔ Pinning سے upgrade ایک دانستہ عمل بن جاتا ہے: پہلے tag میں ترمیم کی جاتی ہے، پھر وہی pull اور recreate کیا جاتا ہے۔ ایسے stack میں جو boot کے دوران database migrate کرتا ہو، دونوں commands چلانے سے پہلے dump تیار رکھیں۔ یہی routine self-hosted Chatwoot support desk ہر version bump کے لیے استعمال کرتا ہے۔
build ان services پر لاگو ہوتا ہے جو build: section ظاہر کرتی ہیں، ان services سمیت جو image: بھی ظاہر کرتی ہیں۔ up -d --build ایک ہی مرحلے میں build اور start کرتا ہے، اور code تبدیل کرتے وقت یہی معمول کا loop ہے۔ --no-cache صرف اس وقت استعمال کریں جب cached layer واضح طور پر stale ہو، کیونکہ یہ ہر layer کو شروع سے rebuild کرتا ہے۔ کچھ projects ایک ہی cloned repo سے دونوں راستے فراہم کرتے ہیں۔ ایسی صورت میں دونوں loops متبادل update paths ہوتے ہیں: self-hosted openGym workout tracker اپنے pinned checkout کو build کرنے کے لیے docker compose up -d --build استعمال کرتا ہے، کیونکہ اس کی latest images pull کرنے سے اس checkout سے نیا release چل سکتا ہے۔
کیا چل رہا ہے
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps صرف چلنے والے containers دکھاتا ہے۔ start کے دوران crash ہونے والی service وہاں اس وقت تک نظر نہیں آتی جب تک آپ -a شامل نہ کریں۔ اس لیے ps میں موجود نہ ہونے والا container، جبکہ ps -a اسے Exited (1) کے طور پر دکھاتا ہو، startup failure کی عام صورت ہے۔ پہلے exit code پڑھیں، پھر logs دیکھیں۔
logs -f بیک وقت ہر service کو follow کرتا ہے اور ہر سطر کے آغاز میں service کا نام شامل کرتا ہے۔ جب services ایک دوسرے سے رابطہ کر رہی ہوں اور واقعات کی ترتیب اہم ہو، تو یہی view مطلوب ہوتا ہے۔ دائرہ محدود کرنے کے لیے service کا نام دیں۔ ایک ایسے container کے لیے --tail=100 اہم ہے جو ایک ماہ سے چل رہا ہو، کیونکہ default پوری history دکھاتا ہے اور terminal کو پیغامات سے بھر دیتا ہے۔ --since 15m اس سوال کا جواب دیتا ہے جو عموماً آپ کے پاس ہوتا ہے: ابھی کیے گئے restart کے دوران کیا ہوا۔
top ہر container کے اندر موجود processes کی فہرست بناتا ہے۔ اس سے یہ فرق واضح ہوتا ہے کہ "container چل رہا ہے" اور "اس کے اندر process چل رہا ہے"۔ ls موجودہ directory سے باہر جا کر host پر چلنے والے Compose projects کو ان کی status کے ساتھ دکھاتا ہے؛ stopped projects شامل کرنے کے لیے -a بھی شامل کریں۔
سروس کے اندر shell حاصل کرنا
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec پہلے سے چل رہے container کے اندر ایک command چلاتا ہے۔ run اسی service definition سے نیا container شروع کرتا ہے۔ جب service اتنی دیر تک برقرار نہ رہے کہ اس میں exec کیا جا سکے، تو یہی درکار ہوتا ہے۔ ہمیشہ run کو --rm کے ساتھ استعمال کریں۔ اس کے بغیر ہر invocation ایک stopped container چھوڑ دیتی ہے، اور یہ جمع ہوتے رہتے ہیں، یہاں تک کہ docker compose ps -a پڑھنا ممکن نہیں رہتا۔
sh کو bash سے پہلے آزمائیں۔ Alpine پر مبنی بعض images میں bash شامل ہوتا ہے، جن میں official PostgreSQL Alpine image بھی شامل ہے۔ جب یہ موجود نہ ہو تو failure message exec: "bash": executable file not found in $PATH ہوتا ہے۔ --no-deps کو run میں شامل کرنے سے service کی dependencies نظرانداز ہو جاتی ہیں۔ اس طرح فوری configuration check کے دوران پوری database boot نہیں ہوتی۔
run --rm web env یہ دیکھنے کا تیز ترین طریقہ ہے کہ تمام .env file، environment: block اور shell variable merge ہونے کے بعد service کو حقیقت میں کون سا environment ملا۔ جب کوئی value غلط ہو تو عموماً وجہ merge order ہوتی ہے، اور Compose env files اور secrets کو کیسے resolve کرتا ہے میں بتایا گیا ہے کہ کون سا source ترجیح پاتا ہے۔
نیٹ ورکس، ports اور name resolution
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksDefault طور پر، Compose ہر service کو ایک ہی project network پر رکھتا ہے، اور ہر service name اس network پر DNS name ہوتا ہے۔ جب image میں getent شامل ہو تو web کے اندر getent hosts db چلانے سے name resolution کی جانچ ہوتی ہے؛ اس سے یہ معلوم نہیں ہوتا کہ db connections قبول کرتا ہے یا نہیں۔ اگر name resolve ہو جائے لیکن connection refused ہو، تو جانچ کریں کہ server چل رہا ہے اور مطلوبہ address اور port پر listening کر رہا ہے؛ صرف 127.0.0.1 پر bind ہونا ایک ممکنہ وجہ ہے۔ یہی network boundary واضح کرتی ہے کہ project کے باہر شروع کیا گیا container، خواہ docker run کے ذریعے ہو یا اپنی الگ stack کے طور پر، jellyfin جیسے service name کو resolve کرنے کے لیے shared network کا محتاج ہوتا ہے۔ جب آپ کی Jellyfin library کے لیے Halcyon front end اس server تک نہ پہنچ سکے جس کی طرف وہ اشارہ کرتا ہے، تو سب سے پہلے یہی جانچ کریں۔ اس model کی باقی تفصیل Compose networks اور service DNS کے کام کرنے کا طریقہ میں ہے۔
port web 80 اس host کا address اور port دکھاتا ہے جس پر container کا port publish کیا گیا ہے۔ اس سے اس وقت اندازہ لگانے کی ضرورت نہیں رہتی جب mapping کسی variable سے آئی ہو۔ کسی port کو publish کرنے سے Docker کے زیر انتظام firewall rule بھی بن جاتا ہے۔ یہ rule آپ کے rules سے پہلے نافذ ہوتا ہے، اس لیے جس service کو آپ private سمجھ رہے تھے وہ internet کے لیے کھلی ہو سکتی ہے۔ اس صورت کی وضاحت published Docker ports، ufw کو bypass کیوں کرتے ہیں میں ہے۔ ان ports کو unpublished چھوڑنا اور services کے سامنے project network پر ایک authentication proxy رکھنا زیادہ محفوظ طریقہ ہے۔ Authentik کو single sign-on layer کے طور پر چلانا یہی configuration فراہم کرتا ہے۔
Volumes اور data
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes پروجیکٹ میں اعلان کردہ named volumes کو فی سطر ایک volume کے طور پر دکھاتا ہے۔ یہ فہرست backup inventory کا صرف ایک حصہ ہے: bind mounts اور configuration files کی بھی جانچ ضروری ہے۔ جب volumes میں ناقابلِ تلافی data موجود ہو تو درست backup command کی اہمیت فہرست جتنی ہی ہوتی ہے۔ اسی لیے PhotoPrism اور Immich کا موازنہ ہر photo server کے لیے dump اور copy commands واضح کرتا ہے۔ cp کسی shell کو کھولے بغیر file کو container میں copy کرتا ہے یا container سے باہر نکالتا ہے۔ اس کے لیے service:path form استعمال ہوتی ہے، جس طرف container ہو۔
down -v external volumes کے علاوہ اعلان کردہ named volumes، اور containers سے منسلک anonymous volumes کو containers کے ساتھ remove کرتا ہے۔ test stack ختم کرنے کے لیے یہ درست command ہے، لیکن ایسے کسی data کے لیے غلط ہے جسے آپ محفوظ رکھنا چاہتے ہیں، کیونکہ اس میں confirmation نہیں ہوتی اور undo کا کوئی طریقہ نہیں ہوتا۔ Bind mounts اس عمل سے محفوظ رہتے ہیں، کیونکہ وہ host filesystem میں موجود ہوتے ہیں۔ blast radius میں یہ فرق ایک وجہ ہے کہ bind mounts اور named volumes کے درمیان سوچ سمجھ کر انتخاب کیا جائے۔
ایسا cleanup جو data ضائع کیے بغیر disk خالی کرے
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans ان containers کو delete کرتا ہے جو project سے وابستہ ہوں لیکن file میں مزید موجود نہ ہوں۔ Service کا نام تبدیل کرنے کے بعد یہی صورت حال بنتی ہے۔ اس کے بغیر وہ containers چلتے رہتے ہیں، اور docker compose ps بطور default running orphan containers بھی شامل کرتا ہے۔
کچھ بھی delete کرنے سے پہلے docker system df دکھاتا ہے کہ disk space کہاں استعمال ہوئی ہے۔ یہ images، containers، local volumes اور build cache کو الگ الگ دکھاتا ہے، اور ہر ایک کے لیے reclaimable مقدار بھی بتاتا ہے۔ image prune -a وہ تمام images remove کرتا ہے جنہیں کوئی container استعمال نہیں کرتا، خواہ ان پر tag ہو یا نہ ہو۔ جس server پر کسی بڑی image کے کئی versions pull کیے گئے ہوں، وہاں عموماً اس سے سب سے زیادہ space خالی ہوتی ہے۔ builder prune بطور default dangling build cache remove کرتا ہے؛ تمام unused build cache remove کرنے کے لیے -a شامل کریں۔
ان میں سے کوئی بھی named volume کو متاثر نہیں کرتا۔ docker volume prune --all، docker compose down -v اور docker volume rm named volumes remove کرتے ہیں۔ سادہ docker volume prune صرف anonymous volumes remove کرتا ہے۔
کسی خرابی سے پہلے فائل کی جانچ
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet کامیابی کی صورت میں تصدیق کرتا ہے اور کچھ بھی پرنٹ نہیں کرتا، اس لیے اسے deployment سے پہلے کے مرحلے یا git hook میں شامل کرنا مناسب ہے۔ سادہ config مکمل طور پر merge اور interpolate کی گئی فائل پرنٹ کرتا ہے۔ اس طرح آپ تصدیق کر سکتے ہیں کہ variable کی value resolve ہوئی ہے اور override فائلیں توقع کے مطابق layer ہوئی ہیں۔ unset variable وہاں خالی value کے طور پر ظاہر ہوتا ہے، اور اس کے ساتھ warning The "X" variable is not set. Defaulting to a blank string. بھی دکھائی جاتی ہے۔
--dry-run ایک global flag ہے، subcommand flag نہیں۔ اس لیے اسے up سے پہلے لکھا جاتا ہے۔ یہ وہ تمام actions پرنٹ کرتا ہے جو Compose انجام دیتا، لیکن کوئی تبدیلی نہیں کرتا۔ اہم stack پر down چلانے سے پہلے اس پر صرف 30 seconds صرف کرنا مفید ہے۔
فائلوں، profiles اور projects کے ساتھ کام کرنا
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dمتعدد -f flags ترتیب کے مطابق merge ہوتے ہیں، اور بعد والی files پہلے والی files کو key کے لحاظ سے override کرتی ہیں۔ ایک base file کے ساتھ production کے لیے ایک چھوٹی override file رکھنے کا یہ معیاری طریقہ ہے، تاہم lists اور maps کے لیے قواعد مختلف ہوتے ہیں۔ اس لیے کسی غیر متوقع نتیجے کی debugging سے پہلے Compose کی متعدد files کے merge ہونے کا طریقہ پڑھیں۔
--profile اس profile سے tagged services کو untagged services کے ساتھ start کرتا ہے۔ اس طرح debug tooling عام up سے باہر رہتی ہے۔ -p project name مقرر کرتا ہے، جس سے ایک ہی stack کی دو copies الگ networks اور الگ volume names کے ساتھ بیک وقت چل سکتی ہیں۔ reboot کے بعد stack دوبارہ چلانے کے لیے restart policy یا ایسی unit استعمال کی جاتی ہے جو آپ کی طرف سے Compose چلاتی ہے۔ اس کی تفصیل boot کے وقت Compose stacks شروع کرنا میں ہے۔
FAQ
docker-compose کو hyphen سے کس چیز نے بدلا؟
Compose V2 اور V5، جنہیں docker compose کے طور پر space کے ساتھ چلایا جاتا ہے۔ Linux پر Compose الگ سے install کیے جانے والے plugin کے طور پر دستیاب ہے؛ Ubuntu 24.04 LTS کی universe repository اب بھی V1 Python tool فراہم کرتی ہے۔ اگر space والی صورت دستیاب نہ ہو تو Docker کی repository configure کریں اور docker-compose-plugin package install کریں۔ پرانے scripts کو alias شامل کرنے کے بجائے space والی صورت میں update کریں، کیونکہ V2 میں ایسے flags موجود ہیں جو V1 میں نہیں تھے۔
docker compose restart میری config میں کی گئی تبدیلی کیوں نہیں پڑھتا؟
restart موجودہ container کو اسی configuration کے ساتھ stop اور start کرتا ہے جس کے ساتھ وہ بنایا گیا تھا، اور یہ compose.yaml کو دوبارہ نہیں پڑھتا۔ Environment variables، ports، volumes یا image tag میں کسی بھی تبدیلی کے لیے docker compose up -d درکار ہے۔ یہ ہر service کا اس کے چلتے ہوئے container سے موازنہ کرتا ہے اور مختلف ہونے والی services کو دوبارہ بناتا ہے۔ جب file میں کوئی تبدیلی نہ ہوئی ہو، تب بھی replacement کرانے کے لیے --force-recreate شامل کریں۔
میں service کو نئی image پر کیسے update کروں؟
docker compose pull چلائیں، پھر docker compose up -d چلائیں۔ Pull ہر tag کے لیے file میں موجود موجودہ image حاصل کرتا ہے، اور up -d ایسی service کو دوبارہ بناتا ہے جس کی image ID اس کے container سے مطابقت نہیں رکھتی۔ صرف up -d چلانے پر pull policy لاگو ہوتی ہے: default missing policy cached images دوبارہ استعمال کرتی ہے، سوائے latest کے، جسے ہمیشہ pull کیا جاتا ہے۔
Live server پر کون سی cleanup commands محفوظ ہیں؟
docker system df کچھ حذف کیے بغیر disk usage رپورٹ کرتا ہے؛ docker image prune -a اور docker builder prune غیر استعمال شدہ images اور build cache حذف کرتے ہیں، اس لیے چلتی ہوئی services کام کرتی رہتی ہیں اور named volumes متاثر نہیں ہوتے۔ خطرناک commands docker compose down -v اور docker volume prune --all ہیں۔ docker compose down -v project کے declared non-external named volumes اور attached anonymous volumes کو بغیر prompt کے حذف کرتا ہے۔ docker volume prune --all غیر استعمال شدہ local volumes، بشمول named volumes، ایک y/N prompt کے بعد حذف کرتا ہے، یا -f کے ساتھ کوئی prompt بھی نہیں دکھاتا۔ پہلے docker compose config --volumes چلائیں تاکہ معلوم ہو کہ کیا خطرے میں ہے۔
کیا میں پورا stack شروع کیے بغیر ایک command چلا سکتا ہوں؟
ہاں۔ docker compose run --rm --no-deps web sh web service definition سے ایک container شروع کرتا ہے، اس کی dependencies کو نظرانداز کرتا ہے، اور آپ کے exit کرنے پر container حذف کر دیتا ہے۔ جب container پہلے سے چل رہا ہو تو exec استعمال کریں، کیونکہ exec آپ کی command کو live container کے اندر چلاتا ہے اور وہ state دکھاتا ہے جس میں service حقیقتاً موجود ہے۔