رفتن به محتوا
LoopX

دستورات پایه

توی این درس یاد می‌گیری دستورهای روزمره‌ی داکر را: کانتینر را در پس‌زمینه (-d) یا به‌صورت تعاملی (-it) اجرا کنی، با --name اسم بدهی، با docker stop و docker start متوقف و دوباره روشنش کنی، با docker rm حذفش کنی، و با --rm کاری کنی که خودش بعد از کار پاک شود. هم‌چنین می‌فهمی چرا docker stop گاهی ۱۰ ثانیه طول می‌کشد.

کانتینر مثل یک دستگاه است و دستورها دکمه‌های ریموت: run (نصب و روشن)، stop (خاموش)، start (دوباره روشن، با همان تنظیمات)، rm (دور انداختن دستگاه). حالت detached (-d) مثل این است که دستگاه را روشن کنی و خودت بروی سراغ کار دیگر؛ حالت تعاملی (-it) مثل این است که جلوی دستگاه بنشینی و با آن حرف بزنی.

حالت پس‌زمینه (-d) برای سرویس‌ها و حالت تعاملی (-it) برای کار مستقیم داخل کانتینر.

مثال ۱: یک وب‌سرور در پس‌زمینه با اسم

Section titled “مثال ۱: یک وب‌سرور در پس‌زمینه با اسم”
Terminal window
docker run -d --name lx-web -p 8310:80 nginx:alpine
sleep 2
docker ps --filter name=lx-web --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
curl -s -o /dev/null -w "HTTP %{http_code}\n" localhost:8310
خروجی
c6c82525aa757c3f160995a0b5a4949d3927b90bf4fa8e515da37f6daf30c308
NAMES IMAGE STATUS
lx-web nginx:alpine Up 2 seconds
HTTP 200
  • -d کانتینر را در پس‌زمینه می‌گذارد و فقط شناسه‌ی بلندش را چاپ می‌کند.
  • --name lx-web اسم خوانایی می‌دهد؛ بعداً به‌جای شناسه‌ی طولانی می‌نویسی docker stop lx-web.
  • -p 8310:80 پورت ۸۰ داخل کانتینر را روی ۸۳۱۰ سیستم می‌گذارد (درس «پورت‌ها» کامل می‌گوید).

مثال ۲: توقف و شروع دوباره

Section titled “مثال ۲: توقف و شروع دوباره”
Terminal window
docker stop lx-web
docker ps -a --filter name=lx-web --format '{{.Names}}: {{.Status}}'
docker start lx-web
sleep 2
docker ps --filter name=lx-web --format '{{.Names}}: {{.Status}}'
خروجی
lx-web
lx-web: Exited (0) Less than a second ago
lx-web
lx-web: Up 2 seconds

docker 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 ندارد):

Terminal window
docker run -i --rm ubuntu:24.04 bash <<'LXEOF'
whoami
hostname
head -2 /etc/os-release
echo "داخل کانتینر Ubuntu هستم"
LXEOF
خروجی
root
ed03dc291972
PRETTY_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 “مثال ۴: نصب برنامه داخل کانتینر و ماندگاری‌اش”
Terminal window
docker run -d --name lx-box ubuntu:24.04 sleep 600 >/dev/null
docker 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/null
docker start lx-box >/dev/null
docker exec lx-box tree --version
خروجی
tree v2.1.1 (c) 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro
tree v2.1.1 (c) 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro

tree را داخل کانتینر نصب کردیم و کانتینر را خاموش و دوباره روشن کردیم؛ هنوز هست. چون این برنامه در لایه‌ی قابل‌نوشتن همان کانتینر است و stop/start آن لایه را نگه می‌دارد. ولی:

Terminal window
docker rm -f lx-box >/dev/null
docker run --rm ubuntu:24.04 sh -c 'tree --version 2>&1 | head -1'
خروجی
sh: 1: tree: not found

با حذف کانتینر، لایه‌ی نوشتنی و برنامه‌ی نصب‌شده رفتند و کانتینر تازه دوباره تمیز است. (برای ماندگاری واقعی از volume یا image جدید استفاده می‌کنی.)

⚡ بررسی سریع

بعد از docker stop و docker start، فایل‌هایی که داخل کانتینر ساخته بودی…

Terminal window
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 کند است؟”
Terminal window
docker run -d --name lx-slow alpine sleep 600 >/dev/null
docker run -d --name lx-quick nginx:alpine >/dev/null
TIMEFORMAT='زمان: %Rs'
echo "sleep:"; time docker stop lx-slow >/dev/null
echo "nginx:"; time docker stop lx-quick >/dev/null
docker rm lx-slow lx-quick >/dev/null
خروجی
sleep:
زمان: 3.573s
nginx:
زمان: 0.389s

docker 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.)

گزینه معنی
-d اجرا در پس‌زمینه
-i نگه داشتن stdin باز
-t تخصیص ترمینال
-it تعاملی (shell)
--name N اسم برای کانتینر
--rm حذف خودکار بعد از پایان
-p H:C پورت میزبان به کانتینر
دستور کار
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 عوض کردن اسم
Terminal window
docker run -d --name lx-web nginx:alpine
خروجی
docker: 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)”
Terminal window
docker run -it --rm alpine echo hi
خروجی
cannot attach stdin to a TTY-enabled container because stdin is not a terminal

-t یک ترمینال می‌خواهد و در اسکریپت یا CI ترمینال وجود ندارد. راه‌حل: در اسکریپت‌ها -t را حذف کن (و فقط -i اگر ورودی لازم است).

۳) «کانتینرم بلافاصله تمام می‌شود»

Section titled “۳) «کانتینرم بلافاصله تمام می‌شود»”
Terminal window
docker run -d --name lx-quick ubuntu:24.04
sleep 2
docker ps -a --filter name=lx-quick --format '{{.Names}}: {{.Status}}'
docker rm lx-quick
خروجی
51b548e27aba56f72d24ad983b2c90893907290382bdf12a603aebd0bea43edf
lx-quick: Exited (0) 2 seconds ago
lx-quick

کانتینر Ubuntu با -d و بدون برنامه‌ی ماندگار بلافاصله Exited (0) می‌شود، چون پروسه‌ی اصلی (bash) ورودی ندارد. راه‌حل: یا یک پروسه‌ی ماندگار بده (sleep 600، سرور)، یا برای کار تعاملی از -it استفاده کن.

۴) فراموش کردن پاک‌سازی

Section titled “۴) فراموش کردن پاک‌سازی”

کانتینرهای متوقف‌شده انباشته می‌شوند. راه‌حل: --rm برای دستورهای موقت و گاهی docker ps -a برای مرور.

✎ تمرینآسان

یک کانتینر alpine بساز که فقط کلمه‌ی salam را چاپ کند و خودش پاک شود.

دیدن جواب
Terminal window
docker run --rm alpine echo salam
خروجی
salam
✎ تمرینمتوسط

یک وب‌سرور nginx با اسم lx-ex1 روی پورت 8311 در پس‌زمینه بالا بیاور، ثابت کن جواب 200 می‌دهد، بعد متوقف و دوباره روشنش کن و بالاخره حذفش کن.

دیدن جواب
Terminal window
docker run -d --name lx-ex1 -p 8311:80 nginx:alpine >/dev/null; sleep 2
curl -s -o /dev/null -w "%{http_code}\n" localhost:8311
docker stop lx-ex1 >/dev/null; docker start lx-ex1 >/dev/null; sleep 2
curl -s -o /dev/null -w "%{http_code}\n" localhost:8311
docker rm -f lx-ex1
خروجی
200
200
lx-ex1
✎ تمرینسخت

داخل یک کانتینر Ubuntu (بدون --rm، با اسم lx-ex2) فایلی به اسم /root/note.txt بساز. ثابت کن بعد از stop و start هنوز هست، ولی با docker rm و ساخت دوباره‌ی کانتینر، نیست. دلیلش را بنویس.

دیدن جواب
Terminal window
docker run -d --name lx-ex2 ubuntu:24.04 sleep 600 >/dev/null
docker exec lx-ex2 sh -c 'echo hi > /root/note.txt'
docker stop -t 1 lx-ex2 >/dev/null; docker start lx-ex2 >/dev/null
docker exec lx-ex2 cat /root/note.txt
docker rm -f lx-ex2 >/dev/null
docker run -d --name lx-ex2 ubuntu:24.04 sleep 600 >/dev/null
docker exec lx-ex2 sh -c 'cat /root/note.txt 2>&1'
docker rm -f lx-ex2 >/dev/null
خروجی
hi
cat: /root/note.txt: No such file or directory

فایل در لایه‌ی قابل‌نوشتن همان کانتینر بود؛ stop/start آن را نگه می‌دارد و rm از بین می‌برد.

؟ آزمونک
  1. گزینه‌ی -d چه می‌کند؟

  2. -it شامل چه چیزهایی است؟

  3. تفاوت docker stop و docker rm؟

  4. چرا docker stop روی یک کانتینر ممکن است ۱۰ ثانیه طول بکشد؟

  5. --rm برای چیست؟

  • -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 bashshell تعاملی یک‌بار‌مصرف
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همه‌ی کانتینرها