توی این درس یاد میگیری دستورهای روزمرهی داکر را: کانتینر را در پسزمینه (-d) یا بهصورت تعاملی (-it) اجرا کنی، با --name اسم بدهی، با docker stop و docker start متوقف و دوباره روشنش کنی، با docker rm حذفش کنی، و با --rm کاری کنی که خودش بعد از کار پاک شود. همچنین میفهمی چرا docker stop گاهی ۱۰ ثانیه طول میکشد.
تشبیه: کنترل تلویزیون
Section titled “تشبیه: کنترل تلویزیون”کانتینر مثل یک دستگاه است و دستورها دکمههای ریموت: run (نصب و روشن)، stop (خاموش)، start (دوباره روشن، با همان تنظیمات)، rm (دور انداختن دستگاه). حالت detached (-d) مثل این است که دستگاه را روشن کنی و خودت بروی سراغ کار دیگر؛ حالت تعاملی (-it) مثل این است که جلوی دستگاه بنشینی و با آن حرف بزنی.
دو حالت اجرا
Section titled “دو حالت اجرا”مثالهای عملی
Section titled “مثالهای عملی”مثال ۱: یک وبسرور در پسزمینه با اسم
Section titled “مثال ۱: یک وبسرور در پسزمینه با اسم”docker run -d --name lx-web -p 8310:80 nginx:alpinesleep 2docker ps --filter name=lx-web --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'curl -s -o /dev/null -w "HTTP %{http_code}\n" localhost:8310c6c82525aa757c3f160995a0b5a4949d3927b90bf4fa8e515da37f6daf30c308NAMES IMAGE STATUSlx-web nginx:alpine Up 2 secondsHTTP 200-dکانتینر را در پسزمینه میگذارد و فقط شناسهی بلندش را چاپ میکند.--name lx-webاسم خوانایی میدهد؛ بعداً بهجای شناسهی طولانی مینویسیdocker stop lx-web.-p 8310:80پورت ۸۰ داخل کانتینر را روی ۸۳۱۰ سیستم میگذارد (درس «پورتها» کامل میگوید).
مثال ۲: توقف و شروع دوباره
Section titled “مثال ۲: توقف و شروع دوباره”docker stop lx-webdocker ps -a --filter name=lx-web --format '{{.Names}}: {{.Status}}'docker start lx-websleep 2docker ps --filter name=lx-web --format '{{.Names}}: {{.Status}}'lx-weblx-web: Exited (0) Less than a second agolx-weblx-web: Up 2 secondsdocker stop کانتینر را خاموش میکند ولی حذف نمیکند؛ با docker ps -a هنوز میبینیش (Exited). docker start همان کانتینر را (با همان اسم، همان تنظیمات و همان فایلها) دوباره روشن میکند. برای بستن و روشن شدن یکجا docker restart lx-web هم هست.
مثال ۳: حالت تعاملی (شبیهسازی -it با ورودی استاندارد)
Section titled “مثال ۳: حالت تعاملی (شبیهسازی -it با ورودی استاندارد)”وقتی docker run -it ubuntu bash را در ترمینال خودت میزنی، یک shell داخل کانتینر باز میشود. -i ورودی استاندارد را باز نگه میدارد و -t یک ترمینال (pseudo-TTY) میسازد. چون اینجا ترمینال تعاملی ندارم، همان رفتار را با -i و دادن دستورها از ورودی نشان میدهم (ماحصل یکی است؛ فقط prompt ندارد):
docker run -i --rm ubuntu:24.04 bash <<'LXEOF'whoamihostnamehead -2 /etc/os-releaseecho "داخل کانتینر Ubuntu هستم"LXEOFrooted03dc291972PRETTY_NAME="Ubuntu 24.04.5 LTS"NAME="Ubuntu"داخل کانتینر Ubuntu هستمدر ترمینال واقعی، با docker run -it --rm ubuntu:24.04 bash یک prompt مثل root@a1b2c3d4e5f6:/# میبینی، هر دستوری میزنی و با exit (یا Ctrl+D) بیرون میآیی؛ --rm هم کانتینر را بعد از خروج پاک میکند. دقت کن کاربر داخل کانتینر root است و hostname شناسهی کانتینر.
مثال ۴: نصب برنامه داخل کانتینر و ماندگاریاش
Section titled “مثال ۴: نصب برنامه داخل کانتینر و ماندگاریاش”docker run -d --name lx-box ubuntu:24.04 sleep 600 >/dev/nulldocker exec lx-box sh -c 'apt-get update -qq >/dev/null 2>&1; apt-get install -y -qq tree >/dev/null 2>&1; tree --version'docker stop -t 1 lx-box >/dev/nulldocker start lx-box >/dev/nulldocker exec lx-box tree --versiontree v2.1.1 (c) 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokorotree v2.1.1 (c) 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokorotree را داخل کانتینر نصب کردیم و کانتینر را خاموش و دوباره روشن کردیم؛ هنوز هست. چون این برنامه در لایهی قابلنوشتن همان کانتینر است و stop/start آن لایه را نگه میدارد. ولی:
docker rm -f lx-box >/dev/nulldocker run --rm ubuntu:24.04 sh -c 'tree --version 2>&1 | head -1'sh: 1: tree: not foundبا حذف کانتینر، لایهی نوشتنی و برنامهی نصبشده رفتند و کانتینر تازه دوباره تمیز است. (برای ماندگاری واقعی از volume یا image جدید استفاده میکنی.)
بعد از docker stop و docker start، فایلهایی که داخل کانتینر ساخته بودی…
stop و start لایهی قابلنوشتن را نگه میدارند؛ فقط docker rm آن را از بین میبرد.
مثال ۵: –rm و تمیز ماندن
Section titled “مثال ۵: –rm و تمیز ماندن”echo "قبل: $(docker ps -aq --filter ancestor=alpine | wc -l | tr -d ' ') کانتینر alpine"docker run --rm alpine echo "یک بار مصرف"echo "بعد: $(docker ps -aq --filter ancestor=alpine | wc -l | tr -d ' ') کانتینر alpine"قبل: 0 کانتینر alpineیک بار مصرفبعد: 0 کانتینر alpineتعداد کانتینرها قبل و بعد یکی است؛ --rm کانتینر را بلافاصله بعد از پایان پروسهی اصلی پاک کرد. برای دستورهای یکبارمصرف و آزمایشها همیشه از --rm استفاده کن تا کانتینر متوقفشده روی هم انباشته نشوند.
مثال ۶: چرا گاهی docker stop کند است؟
Section titled “مثال ۶: چرا گاهی docker stop کند است؟”docker run -d --name lx-slow alpine sleep 600 >/dev/nulldocker run -d --name lx-quick nginx:alpine >/dev/nullTIMEFORMAT='زمان: %Rs'echo "sleep:"; time docker stop lx-slow >/dev/nullecho "nginx:"; time docker stop lx-quick >/dev/nulldocker rm lx-slow lx-quick >/dev/nullsleep:زمان: 3.573snginx:زمان: 0.389sdocker stop ابتدا سیگنال TERM میفرستد (درخواست مؤدبانه برای تمام کردن) و تا ۱۰ ثانیه (مهلت پیشفرض) صبر میکند؛ اگر پروسه تمام نشد، سیگنال KILL میفرستد. nginx به TERM درست جواب میدهد و در کسری از ثانیه بسته میشود؛ sleep بهعنوان PID 1 سیگنال را نادیده میگیرد و چند ثانیه (تا حداکثر مهلت) منتظر میماند و در آخر با KILL بسته میشود (کد خروج ۱۳۷). زمان دقیق در هر اجرا فرق میکند. مهلت با -t عوض میشود (docker stop -t 1 ...).
پشت پرده: وقتی docker run اجرا میشود
Section titled “پشت پرده: وقتی docker run اجرا میشود”docker run در واقع چند کار پشت سر هم است: ۱) اگر image نبود، pull؛ ۲) create (ساخت کانتینر و لایهی نوشتنی)؛ ۳) start؛ ۴) اگر -d نبود، attach (وصل کردن ترمینال تو به خروجی/ورودی کانتینر). تفاوت -d با حالت پیشفرض فقط مرحلهی چهارم است.
-i(interactive): ورودی استاندارد (stdin) کانتینر را باز نگه میدارد.-t(tty): یک pseudo-terminal میسازد تا خروجی و رنگ و ویرایش خط درست کار کند.-it: هر دو، برای shell تعاملی.
پروسهی اصلی کانتینر PID 1 است؛ اگر تمام شود، کانتینر تمام میشود، و سیگنالهای docker stop به همین پروسه میرسند. (جزئیاتش در درس CMD در برابر ENTRYPOINT.)
جدولهای مرجع
Section titled “جدولهای مرجع”گزینههای docker run
Section titled “گزینههای docker run”| گزینه | معنی |
|---|---|
-d |
اجرا در پسزمینه |
-i |
نگه داشتن stdin باز |
-t |
تخصیص ترمینال |
-it |
تعاملی (shell) |
--name N |
اسم برای کانتینر |
--rm |
حذف خودکار بعد از پایان |
-p H:C |
پورت میزبان به کانتینر |
دستورهای چرخهی عمر
Section titled “دستورهای چرخهی عمر”| دستور | کار |
|---|---|
docker stop N |
TERM، بعد از مهلت KILL |
docker start N |
روشن کردن کانتینر متوقفشده |
docker restart N |
stop + start |
docker kill N |
فوراً KILL |
docker rm N |
حذف (با -f برای در حال اجرا) |
docker rename A B |
عوض کردن اسم |
اشتباهات رایج
Section titled “اشتباهات رایج”۱) اسم تکراری
Section titled “۱) اسم تکراری”docker run -d --name lx-web nginx:alpinedocker: Error response from daemon: Conflict. The container name "/lx-web" is already in use by container "c6c82525aa757c3f160995a0b5a4949d3927b90bf4fa8e515da37f6daf30c308". You have to remove (or rename) that container to be able to reuse that name.
Run 'docker run --help' for more informationاسم lx-web را قبلاً کانتینر دیگری گرفته (حتی اگر متوقف باشد). راهحل: docker rm lx-web یا اسم دیگری بده.
۲) -it بدون ترمینال (در اسکریپت و CI)
Section titled “۲) -it بدون ترمینال (در اسکریپت و CI)”docker run -it --rm alpine echo hicannot attach stdin to a TTY-enabled container because stdin is not a terminal-t یک ترمینال میخواهد و در اسکریپت یا CI ترمینال وجود ندارد. راهحل: در اسکریپتها -t را حذف کن (و فقط -i اگر ورودی لازم است).
۳) «کانتینرم بلافاصله تمام میشود»
Section titled “۳) «کانتینرم بلافاصله تمام میشود»”docker run -d --name lx-quick ubuntu:24.04sleep 2docker ps -a --filter name=lx-quick --format '{{.Names}}: {{.Status}}'docker rm lx-quick51b548e27aba56f72d24ad983b2c90893907290382bdf12a603aebd0bea43edflx-quick: Exited (0) 2 seconds agolx-quickکانتینر Ubuntu با -d و بدون برنامهی ماندگار بلافاصله Exited (0) میشود، چون پروسهی اصلی (bash) ورودی ندارد. راهحل: یا یک پروسهی ماندگار بده (sleep 600، سرور)، یا برای کار تعاملی از -it استفاده کن.
۴) فراموش کردن پاکسازی
Section titled “۴) فراموش کردن پاکسازی”کانتینرهای متوقفشده انباشته میشوند. راهحل: --rm برای دستورهای موقت و گاهی docker ps -a برای مرور.
یک کانتینر alpine بساز که فقط کلمهی salam را چاپ کند و خودش پاک شود.
دیدن جواب
docker run --rm alpine echo salamsalamیک وبسرور nginx با اسم lx-ex1 روی پورت 8311 در پسزمینه بالا بیاور، ثابت کن جواب 200 میدهد، بعد متوقف و دوباره روشنش کن و بالاخره حذفش کن.
دیدن جواب
docker run -d --name lx-ex1 -p 8311:80 nginx:alpine >/dev/null; sleep 2curl -s -o /dev/null -w "%{http_code}\n" localhost:8311docker stop lx-ex1 >/dev/null; docker start lx-ex1 >/dev/null; sleep 2curl -s -o /dev/null -w "%{http_code}\n" localhost:8311docker rm -f lx-ex1200200lx-ex1داخل یک کانتینر Ubuntu (بدون --rm، با اسم lx-ex2) فایلی به اسم /root/note.txt بساز. ثابت کن بعد از stop و start هنوز هست، ولی با docker rm و ساخت دوبارهی کانتینر، نیست. دلیلش را بنویس.
دیدن جواب
docker run -d --name lx-ex2 ubuntu:24.04 sleep 600 >/dev/nulldocker exec lx-ex2 sh -c 'echo hi > /root/note.txt'docker stop -t 1 lx-ex2 >/dev/null; docker start lx-ex2 >/dev/nulldocker exec lx-ex2 cat /root/note.txtdocker rm -f lx-ex2 >/dev/nulldocker run -d --name lx-ex2 ubuntu:24.04 sleep 600 >/dev/nulldocker exec lx-ex2 sh -c 'cat /root/note.txt 2>&1'docker rm -f lx-ex2 >/dev/nullhicat: /root/note.txt: No such file or directoryفایل در لایهی قابلنوشتن همان کانتینر بود؛ stop/start آن را نگه میدارد و rm از بین میبرد.
آزمونک
Section titled “آزمونک”گزینهی -d چه میکند؟
detached: کانتینر در پسزمینه میماند و فقط شناسهاش چاپ میشود.
-it شامل چه چیزهایی است؟
برای کار تعاملی با shell داخل کانتینر.
تفاوت docker stop و docker rm؟
بعد از stop هنوز با docker ps -a میبینیش و میتوانی start کنی.
چرا docker stop روی یک کانتینر ممکن است ۱۰ ثانیه طول بکشد؟
مهلت پیشفرض ۱۰ ثانیه است و با -t عوض میشود.
--rm برای چیست؟
برای دستورهای موقت؛ کانتینر متوقفشده انباشته نمیشود.
جمعبندی
Section titled “جمعبندی”-dبرای سرویسها در پسزمینه،-itبرای shell تعاملی،--nameبرای اسم،--rmبرای پاک شدن خودکار.docker stop(TERM بعد KILL) وdocker startکانتینر را خاموش و روشن میکنند و فایلها میمانند؛docker rmهمهچیز را از بین میبرد.docker run= pull (اگر لازم) + create + start + attach (اگر بدون-d).- کانتینر وقتی پروسهی اصلیاش تمام شود تمام میشود.
-tدر اسکریپت بدون ترمینال خطا میدهد؛ برای CI حذفش کن.
| دستور | کاری که میکند |
|---|---|
docker run -d --name web nginx | اجرا در پسزمینه با اسم |
docker run -it --rm ubuntu bash | shell تعاملی یکبارمصرف |
docker run --rm IMG CMD | اجرای یک دستور و پاک شدن |
docker stop web | توقف مؤدبانه (TERM بعد KILL) |
docker stop -t 1 web | مهلت ۱ ثانیه |
docker start web | روشن کردن دوباره |
docker restart web | توقف و شروع |
docker rm web | حذف کانتینر متوقفشده |
docker rm -f web | حذف اجباری |
docker exec CONTAINER CMD | اجرای دستور در کانتینر در حال اجرا |
docker ps -a | همهی کانتینرها |