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

داکر چیست؟

توی این درس یاد می‌گیری داکر (Docker) دقیقاً چه مشکلی را حل می‌کند، کانتینر (container) یعنی چه و چه فرقی با یک برنامه‌ی معمولی دارد، سه مفهوم اصلی image و container و registry چه نقشی دارند، و داکر در عمق (با namespace، cgroup و لایه‌ها) چطور کار می‌کند. در آخر هم با شش مثال واقعی دست‌به‌کار می‌شوی، از docker --version تا بالا آوردن یک وب‌سرور.

مشکل: «روی سیستم من که کار می‌کرد!»

Section titled “مشکل: «روی سیستم من که کار می‌کرد!»”

فرض کن یک برنامه‌ی وب نوشته‌ای. روی لپ‌تاپ خودت عالی کار می‌کند. آن را برای همکارت می‌فرستی و او می‌گوید: «ارور می‌دهد.»

چرا؟ چون برنامه‌ی تو فقط کد نیست. به یک مجموعه چیز دیگر هم وابسته است:

  • نسخه‌ی مشخصی از زبان برنامه‌نویسی (مثلاً Node.js 22 یا Python 3.12)
  • چند کتابخانه با نسخه‌های مشخص
  • یک دیتابیس با تنظیمات خاص
  • متغیرهای محیطی، پورت‌ها، فایل‌های تنظیمات
  • و حتی خود سیستم‌عامل (ویندوز، مک یا لینوکس؟ کدام نسخه؟)

روی لپ‌تاپ تو همه‌ی این‌ها «اتفاقاً» درست‌اند. روی لپ‌تاپ همکارت، یا روی سروری که قرار است برنامه آنجا اجرا شود، یکی‌شان فرق دارد. نتیجه همان جمله‌ی معروف است: «works on my machine».

راه‌حل: همه‌چیز را با هم بسته‌بندی کن

Section titled “راه‌حل: همه‌چیز را با هم بسته‌بندی کن”

تشبیه ساده‌اش کانتینر باری است.

قبل از اختراع کانتینر، کشتی‌ها هر کالا را جداگانه بار می‌کردند: کیسه، جعبه، بشکه، هر کدام با شکل و اندازه‌ی خودش. بارگیری کند بود و هر بندر روش خودش را داشت. بعد کسی فکر کرد: همه‌چیز را داخل یک جعبه‌ی استاندارد بگذاریم. حالا هر چه داخلش باشد، کشتی و جرثقیل و کامیون فقط با یک چیز کار دارند: جعبه‌ی هم‌اندازه.

داکر همین کار را برای نرم‌افزار می‌کند. برنامه‌ات را با تمام چیزهایی که لازم دارد (زبان برنامه‌نویسی، کتابخانه‌ها، تنظیمات) داخل یک «جعبه» می‌گذارد. این جعبه را کانتینر می‌گویند. هر جا که داکر باشد، آن جعبه همان‌طور که هست اجرا می‌شود: لپ‌تاپ تو، لپ‌تاپ همکارت، یا یک سرور در آن سر دنیا.

داکر از چه تکه‌هایی ساخته شده؟

Section titled “داکر از چه تکه‌هایی ساخته شده؟”

وقتی می‌گویی «داکر»، در واقع چند برنامه با هم کار می‌کنند. این نمودار تصویر کلی را نشان می‌دهد؛ در بخش «پشت پرده» به هر تکه برمی‌گردیم.

معماری داکر: تو دستور می‌دهی، daemon کار را انجام می‌دهد و در نهایت هسته‌ی لینوکس کانتینر را اجرا می‌کند.
تکه وظیفه
docker CLI برنامه‌ای که تو در ترمینال با آن حرف می‌زنی. فقط دستور تو را به daemon می‌فرستد
dockerd (daemon) مغز داکر. image ها، کانتینرها، شبکه‌ها و volume ها را مدیریت می‌کند و در پس‌زمینه همیشه روشن است
Registry انبار image ها (مثل Docker Hub). image را از آنجا می‌گیری (pull) یا آنجا می‌گذاری (push)
containerd مدیریت چرخه‌ی عمر کانتینر: ساخت، شروع، توقف
runc ابزار سطح پایینی که کانتینر را واقعاً می‌سازد و اجرا می‌کند
هسته‌ی لینوکس ویژگی‌هایی مثل namespace و cgroup که جداسازی را ممکن می‌کنند

این سه کلمه را همین حالا خوب یاد بگیر. تا آخر دوره هر روز می‌شنوی‌شان.

مفهوم یعنی چه؟ تشبیه
Image (ایمیج) یک قالب فقط‌خواندنی که همه‌ی چیزهای لازم برنامه در آن است دستور پخت و مواد اولیه‌ی بسته‌بندی‌شده
Container (کانتینر) یک نمونه‌ی در حال اجرا از یک image غذایی که از روی آن دستور پخته شده و الان سر میز است
Registry (رجیستری) انباری که image ها آنجا ذخیره و به اشتراک گذاشته می‌شوند یک فروشگاه یا کتابخانه‌ی آنلاین. معروف‌ترینش Docker Hub است

از روی یک image می‌توانی هر چند کانتینر که بخواهی بسازی، همان‌طور که از یک دستور پخت می‌شود چندین بار غذا پخت. هر کانتینر مستقل از بقیه است.

یک image در registry هست؛ آن را pull می‌کنی و از رویش هر چند کانتینر که بخواهی می‌سازی. هر کانتینر وضعیت خودش را دارد (یکی ممکن است متوقف باشد).

از ساده شروع می‌کنیم و کم‌کم به چیزهای واقعی می‌رسیم. همه‌ی خروجی‌ها از اجرای واقعی روی یک سیستم با Docker Desktop گرفته شده‌اند؛ شناسه‌ها، تاریخ‌ها و نسخه‌ها روی سیستم تو فرق می‌کنند.

مثال ۱: داکر نصب است؟ کدام نسخه؟

Section titled “مثال ۱: داکر نصب است؟ کدام نسخه؟”
Terminal window
docker --version
خروجی
Docker version 29.8.1, build 4a63305

این فقط نسخه‌ی برنامه‌ی docker (همان CLI) را می‌گوید. برای دیدن هر دو طرف، یعنی CLI و daemon:

Terminal window
docker version --format 'Client: {{.Client.Version}} ({{.Client.Os}}/{{.Client.Arch}}){{"\n"}}Server: {{.Server.Version}} ({{.Server.Os}}/{{.Server.Arch}})'
خروجی
Client: 29.8.1 (darwin/arm64)
Server: 29.8.1 (linux/arm64)

به یک نکته‌ی جالب دقت کن: Client روی darwin (macOS) است ولی Server روی linux. یعنی daemon روی یک لینوکس اجرا می‌شود حتی وقتی سیستم تو مک است. چرا؟ در بخش «پشت پرده» توضیح می‌دهم. اگر docker version خطا داد که به daemon وصل نمی‌شود، یعنی داکر روشن نیست (در Docker Desktop برنامه را باز کن).

مثال ۲: اولین کانتینر، hello-world

Section titled “مثال ۲: اولین کانتینر، hello-world”
Terminal window
docker run hello-world
خروجی (خلاصه)
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
58dee6a49ef1: Pull complete
Digest: sha256:5e23090353324d887c48ad5e5c56d294eab81588df9605b07d1afe895f9cc8f8
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.

خط‌به‌خط بخوانیم:

  1. Unable to find image ... locally: داکر اول روی سیستم خودت دنبال image گشت و پیدا نکرد.
  2. Pulling from library/hello-world: پس آن را از registry (Docker Hub) pull کرد، یعنی دانلود کرد.
  3. Hello from Docker!: از آن image یک کانتینر ساخت، اجرایش کرد، و برنامه‌ی داخلش این پیام را چاپ کرد. بعد از چاپ، کار برنامه تمام شد و کانتینر خودش بسته شد.

در یک دستور، هر سه مفهوم را دیدی: registry (Docker Hub)، image (hello-world) و container (چیزی که اجرا شد).

⚡ بررسی سریع

در خروجی docker run hello-world، عبارت «Pulling from library/hello-world» یعنی چه؟

مثال ۳: image و container کجا ماندند؟

Section titled “مثال ۳: image و container کجا ماندند؟”
Terminal window
docker images hello-world
خروجی
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
hello-world:latest 5e2309035332 22.6kB 10.3kB U

image هنوز روی سیستم هست؛ دفعه‌ی بعد دیگر دانلود نمی‌شود. و کانتینری که اجرا شد؟

Terminal window
docker ps -a --filter ancestor=hello-world --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}'
خروجی
CONTAINER ID IMAGE STATUS
b4a3840b9a96 hello-world Exited (0) Less than a second ago

کانتینر هم هنوز هست، ولی با وضعیت Exited (0): کارش تمام شده (کد خروج 0 یعنی بدون خطا). docker ps فقط کانتینرهای در حال اجرا را نشان می‌دهد؛ -a (all) همه را، حتی متوقف‌شده‌ها.

مثال ۴: یک لینوکس دیگر داخل سیستم تو

Section titled “مثال ۴: یک لینوکس دیگر داخل سیستم تو”
Terminal window
docker run --rm ubuntu:24.04 cat /etc/os-release
خروجی (چند خط اول)
PRETTY_NAME="Ubuntu 24.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"

این دستور یک کانتینر از image با اسم ubuntu و تگ (tag، یعنی نسخه) 24.04 ساخت، داخلش cat /etc/os-release را اجرا کرد و کانتینر را بست. --rm یعنی «بعد از تمام شدن، کانتینر را خودکار پاک کن» تا کانتینرهای متوقف‌شده انباشته نشوند.

سیستم‌عامل داخل کانتینر Ubuntu است، حتی اگر سیستم تو مک یا ویندوز باشد. روی همان سیستم من، دستور uname -s بیرون از کانتینر Darwin (macOS) می‌گوید. این یعنی کانتینر یک «محیط جدا» است که چیزهای خودش را دارد.

مثال ۵: یک وب‌سرور واقعی

Section titled “مثال ۵: یک وب‌سرور واقعی”

حالا چیزی بسازیم که واقعاً کار کند: وب‌سرور nginx.

Terminal window
docker run -d -p 8099:80 --name lx-web nginx
خروجی (انتهای آن)
Status: Downloaded newer image for nginx:latest
527352eda9a71f578450e190b15d4eb89a1be863cecf8e389ea3f147a622b826

سه گزینه‌ی جدید:

  • -d (detached): کانتینر را در پس‌زمینه اجرا کن و ترمینال را آزاد بگذار.
  • -p 8099:80: پورت 8099 سیستم خودت را به پورت 80 داخل کانتینر وصل کن (به ترتیب پورت-سیستم:پورت-کانتینر).
  • --name lx-web: اسمی که خودمان به کانتینر می‌دهیم، تا بعداً راحت صدایش کنیم.

خروجی، شناسه‌ی بلند کانتینر است. ببینیم زنده است:

Terminal window
docker ps --filter name=lx-web --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}'
خروجی
CONTAINER ID IMAGE STATUS PORTS NAMES
527352eda9a7 nginx Up Less than a second 0.0.0.0:8099->80/tcp, [::]:8099->80/tcp lx-web

و واقعاً جواب می‌دهد؟

Terminal window
curl -s localhost:8099 | head -5
خروجی
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

مرورگرت را هم باز کن و برو به http://localhost:8099؛ صفحه‌ی «Welcome to nginx!» را می‌بینی. یک وب‌سرور کامل را بدون نصب هیچ چیز روی سیستمت بالا آوردی.

مثال ۶: بازرسی و تمیزکاری

Section titled “مثال ۶: بازرسی و تمیزکاری”

لاگ‌های کانتینر (آخرین خط‌ها):

Terminal window
docker logs lx-web
خروجی (انتهای آن)
2026/10/01 13:51:09 [notice] 1#1: start worker process 36
192.168.65.1 - - [01/Oct/2026:13:51:11 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.7.1" "-"

درخواستی که با curl زدیم همین‌جا ثبت شده. و پروسه‌های داخل کانتینر:

Terminal window
docker top lx-web
خروجی (خلاصه)
UID PID PPID C STIME TTY TIME CMD
root 1806 1783 0 13:51 ? 00:00:00 nginx: master process nginx -g daemon off;
statd 1849 1806 0 13:51 ? 00:00:00 nginx: worker process

یک نکته‌ی کلیدی: کانتینر چیزی جز یک پروسه (یا چند پروسه) روی سیستم نیست. حالا ببندیمش و پاکش کنیم:

Terminal window
docker stop lx-web
docker rm lx-web
خروجی
lx-web
lx-web

stop کانتینر را متوقف می‌کند و rm آن را حذف می‌کند. (image nginx سر جایش می‌ماند؛ برای حذف آن docker rmi nginx است.)

پشت پرده: داکر در عمق چطور کار می‌کند؟

Section titled “پشت پرده: داکر در عمق چطور کار می‌کند؟”

تا اینجا داکر را مثل یک جعبه‌ی سیاه دیدیم. حالا بازش کنیم. سه ایده هست که همه‌چیز را توضیح می‌دهند.

۱) کانتینر یک پروسه‌ی جداشده است (namespace)

Section titled “۱) کانتینر یک پروسه‌ی جداشده است (namespace)”

کانتینر ماشین مجازی نیست. هیچ سیستم‌عامل جداگانه‌ای در آن بوت نمی‌شود. کانتینر فقط یک پروسه‌ی معمولی لینوکس است که هسته (kernel) با ویژگی‌ای به اسم namespace برایش «توهم یک سیستم جدا» می‌سازد: پروسه فقط پروسه‌های خودش را می‌بیند، اسم کامپیوتر (hostname) مخصوص خودش را دارد، شبکه و فایل‌سیستم خودش را دارد.

ببین:

Terminal window
docker run --rm ubuntu:24.04 sh -c 'echo "PID inside: $$"; echo "hostname: $(hostname)"; echo "processes:"; ls /proc | grep -E "^[0-9]+$"'
خروجی
PID inside: 1
hostname: c0946a1c7a82
processes:
1
7
8

داخل کانتینر پروسه‌ی اصلی شماره‌ی ۱ دارد (مثل اولین پروسه‌ی یک سیستم تازه‌بوت‌شده)، و hostname کانتینر همان شناسه‌ی کوتاهش است. فقط سه پروسه می‌بیند: خود sh (شماره‌ی ۱) و دو دستور ls و grep که همین الان اجرا کردیم. کل پروسه‌های سیستم را نمی‌بیند. دیوار namespace همین است. (در docker top مثال قبل، همان پروسه‌ی nginx از بیرون با شماره‌ی 1806 دیده می‌شد؛ یک پروسه، دو شماره.)

۲) منابع را محدود می‌کنیم (cgroup)

Section titled “۲) منابع را محدود می‌کنیم (cgroup)”

ویژگی دوم هسته cgroup (control group) است که مشخص می‌کند یک پروسه چقدر CPU و حافظه می‌تواند بگیرد:

Terminal window
docker run --rm --memory 100m ubuntu:24.04 cat /sys/fs/cgroup/memory.max
docker run --rm ubuntu:24.04 cat /sys/fs/cgroup/memory.max
خروجی
104857600
max

با --memory 100m عدد 104857600 بایت (یعنی دقیقاً ۱۰۰ مگابایت: ۱۰۰ × ۱۰۲۴ × ۱۰۲۴) به‌عنوان سقف حافظه ثبت شد. بدون آن، max است، یعنی بدون سقف. اگر پروسه‌ی داخل کانتینر بیشتر از ۱۰۰ مگابایت بخواهد، هسته آن را می‌بندد.

۳) فایل‌ها لایه‌لایه‌اند (union filesystem)

Section titled “۳) فایل‌ها لایه‌لایه‌اند (union filesystem)”

image یک فایل بزرگ و یکپارچه نیست؛ پشته‌ای از لایه‌های فقط‌خواندنی است. هر لایه تغییراتی را روی لایه‌ی زیرین‌اش اضافه می‌کند:

Terminal window
docker image inspect nginx --format 'layers: {{len .RootFS.Layers}}'
docker history nginx --format 'table {{.CreatedBy}}\t{{.Size}}' | head -6
خروجی (خلاصه)
layers: 7
CREATED BY SIZE
CMD ["nginx" "-g" "daemon off;"] 0B
STOPSIGNAL SIGQUIT 0B
EXPOSE map[80/tcp:{}] 0B
ENTRYPOINT ["/docker-entrypoint.sh"] 0B
COPY 30-tune-worker-processes.sh /docker-ent… 16.4kB

image nginx هفت لایه دارد، و docker history نشان می‌دهد هر کدام با چه دستوری ساخته شده‌اند (از جدید به قدیم). وقتی از image کانتینر می‌سازی، داکر یک لایه‌ی نازک قابل‌نوشتن روی همه‌ی این‌ها می‌گذارد:

لایه‌های image مشترک و فقط‌خواندنی‌اند. هر کانتینر یک لایه‌ی قابل‌نوشتن مخصوص خودش دارد. پس ده کانتینر از یک image، لایه‌های image را فقط یک بار روی دیسک ذخیره می‌کنند.

هر تغییری که داخل کانتینر بدهی (فایل بسازی، چیزی را پاک کنی) در همین لایه‌ی بالایی ثبت می‌شود. با docker diff می‌توانی ببینی:

Terminal window
docker run --name lx-a ubuntu:24.04 sh -c 'echo hi > /tmp/x && cat /tmp/x'
docker diff lx-a
docker run --rm ubuntu:24.04 cat /tmp/x
خروجی
hi
C /tmp
A /tmp/x
cat: /tmp/x: No such file or directory

حرف A (Added) یعنی فایل جدید اضافه شد و C (Changed) یعنی پوشه تغییر کرد. ولی کانتینر دیگری که از همان image ساخته شد، فایل /tmp/x را ندارد، چون آن فایل فقط در لایه‌ی قابل‌نوشتن کانتینر lx-a است. و اگر lx-a را حذف کنی (docker rm lx-a)، آن لایه و آن فایل هم برای همیشه می‌روند. این دقیقاً دلیل وجود volume است که در درس‌های بعد یاد می‌گیری.

⚡ بررسی سریع

چرا کانتینر دیگری که از همان image ساخته شد، فایل /tmp/x را ندارد؟

داکر روی مک و ویندوز چطور کار می‌کند؟

Section titled “داکر روی مک و ویندوز چطور کار می‌کند؟”

namespace و cgroup ویژگی‌های هسته‌ی لینوکس هستند. مک و ویندوز این هسته را ندارند. پس Docker Desktop در پس‌زمینه یک ماشین مجازی سبک لینوکسی اجرا می‌کند و daemon داخل آن است. وقتی در ترمینال مک دستور docker می‌زنی، CLI با آن VM حرف می‌زند. همین است که در مثال ۱ دیدیم Client روی darwin و Server روی linux بود. روی ویندوز هم همین‌طور است و VM روی WSL 2 اجرا می‌شود (همان چیزی که در درس اول بخش لینوکس نصب کردی). برای همین نصب داکر روی ویندوز به WSL 2 نیاز دارد.

برای دیدن همین موضوع روی سیستم خودت:

Terminal window
docker info --format 'Server: {{.ServerVersion}}
OS: {{.OperatingSystem}}
Kernel: {{.KernelVersion}}
Runtime: {{.DefaultRuntime}}'
خروجی (نمونه)
Server: 29.8.1
OS: Docker Desktop
Kernel: 7.0.14-linuxkit
Runtime: runc

Kernel: ...-linuxkit یعنی هسته‌ی لینوکسِ داخل آن VM، و Runtime: runc همان ابزاری است که در نمودار معماری دیدی.

Image Container
ماهیت قالب ثابت و فقط‌خواندنی نمونه‌ی زنده (یا متوقف‌شده)
تغییر می‌کند؟ نه بله (لایه‌ی قابل‌نوشتن)
تعداد یک نسخه هر چند تا از یک image
فهرست کردن docker images docker ps و docker ps -a
حذف docker rmi docker rm
تشبیه دستور پخت غذای پخته‌شده

گزینه‌های پرکاربرد docker run

Section titled “گزینه‌های پرکاربرد docker run”
گزینه معنی
-d اجرا در پس‌زمینه (detached)
-p میزبان:کانتینر وصل کردن پورت سیستم به پورت کانتینر
--name اسم دادن اسم به کانتینر
--rm حذف خودکار کانتینر بعد از تمام شدن
--memory 100m سقف حافظه (cgroup)
-it حالت تعاملی با ترمینال (در درس‌های بعد)
-e ، -v متغیر محیطی و volume (در درس‌های بعد)
وضعیت یعنی
Up ... در حال اجرا
Exited (0) تمام شد، بدون خطا
Exited (1) یا عدد دیگر با خطا بسته شد
Created ساخته شده ولی هنوز شروع نشده

اگر یک کانتینر روی پورت 8099 سیستم داری و یکی دیگر را هم روی همان پورت بالا بیاوری:

Terminal window
docker run -d -p 8099:80 --name lx-web2 nginx
خطا
docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint lx-web2 (049243535be9...): Bind for 0.0.0.0:8099 failed: port is already allocated

port is already allocated یعنی «پورت ۸۰۹۹ سیستم را قبلاً کسی گرفته». راه‌حل: یا یک پورت دیگر بده (-p 8100:80)، یا با docker ps ببین کدام کانتینر آن پورت را گرفته و آن را stop کن. یادت هست در درس پروسه‌ها و پورت‌ها هم خطای مشابه (Address already in use) را دیدی؟ همان مفهوم است.

Terminal window
docker run -d --name lx-web nginx
خطا
docker: Error response from daemon: Conflict. The container name "/lx-web" is already in use by container "6f9fc794369f...". You have to remove (or rename) that container to be able to reuse that name.

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

۳) «image را نمی‌توانی پاک کنی»

Section titled “۳) «image را نمی‌توانی پاک کنی»”
Terminal window
docker rmi nginx
خطا
Error response from daemon: conflict: unable to delete nginx:latest (must be forced) - container 527352eda9a7 is using its referenced image abe47724e466

تا وقتی کانتینری (حتی متوقف‌شده) از آن image ساخته شده، نمی‌شود image را پاک کرد. راه‌حل: اول کانتینر را docker rm کن، بعد docker rmi. (استفاده از -f ممکن است ولی بهتر است وقتی دلیلش را می‌دانی.)

۴) «کانتینرم ساخته شد ولی در docker ps نیست!»

Section titled “۴) «کانتینرم ساخته شد ولی در docker ps نیست!»”
Terminal window
docker run -d --name lx-up ubuntu:24.04
docker ps --filter name=lx-up --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}'
docker ps -a --filter name=lx-up --format 'table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.Status}}'
خروجی (بعد از خط شناسه‌ی کانتینر)
CONTAINER ID IMAGE STATUS
CONTAINER ID IMAGE COMMAND STATUS
a6824b661bfc ubuntu:24.04 "/bin/bash" Exited (0) 1 second ago

دستور اول فقط سرستون‌ها را چاپ کرد (هیچ کانتینر در حال اجرایی نیست) و دستور دوم کانتینر متوقف‌شده را نشان داد.

یادت هست گفتیم کانتینر یک پروسه است؟ وقتی پروسه‌ی اصلی تمام شود، کانتینر هم تمام می‌شود. در image اوبونتو (Ubuntu) پروسه‌ی اصلی bash است و چون هیچ ترمینالی به آن وصل نیست، همان لحظه خارج می‌شود. کانتینر خراب نشد؛ فقط کارش تمام شد. برای نگه داشتن، باید پروسه‌ای بدهی که ادامه بدهد (مثل وب‌سرور nginx که داخلش nginx -g daemon off; همیشه می‌ماند). تمیزکاری: docker rm lx-up.

✎ تمرینآسان

با یک دستور از یک کانتینر ubuntu بخواه که جمله‌ی Hello from a container را چاپ کند، و کانتینر بعد از کار خودکار پاک شود.

دیدن جواب
Terminal window
docker run --rm ubuntu:24.04 echo "Hello from a container"
خروجی
Hello from a container

--rm کانتینر را بعد از تمام شدن پاک می‌کند. اگر docker ps -a بزنی اثری از آن نیست.

✎ تمرینمتوسط

یک وب‌سرور nginx با اسم lx-ex روی پورت 8100 سیستم‌ات بالا بیاور. با curl ثابت کن جواب 200 می‌دهد. بعد آن را متوقف و حذف کن و ثابت کن دیگر وجود ندارد.

دیدن جواب
Terminal window
docker run -d -p 8100:80 --name lx-ex nginx
curl -s -o /dev/null -w "%{http_code}\n" localhost:8100
docker stop lx-ex
docker rm lx-ex
docker ps -a --filter name=lx-ex -q | wc -l
خروجی (به ترتیب)
01e94a9deb37...
200
lx-ex
lx-ex
0

دستور آخر شناسه‌ی کانتینرهایی با آن اسم را می‌شمارد و 0 یعنی هیچ. (اگر curl را فوراً بعد از run زدی و خطا گرفتی، دو ثانیه صبر کن تا nginx بالا بیاید.)

✎ تمرینسخت

دو کانتینر از یک image بساز: کانتینر lx-a فایلی به اسم /tmp/note.txt با محتوای hello بسازد، و کانتینر lx-b فقط محتوای /tmp را فهرست کند. بدون ورود به کانتینر ثابت کن فایل فقط در lx-a وجود دارد. بعد توضیح بده چرا، و هر دو را پاک کن.

دیدن جواب
Terminal window
docker run --name lx-a ubuntu:24.04 sh -c 'echo hello > /tmp/note.txt'
docker run --name lx-b ubuntu:24.04 sh -c 'ls /tmp'
docker diff lx-a
docker diff lx-b
docker rm lx-a lx-b
خروجی
C /tmp
A /tmp/note.txt

دستور ls /tmp در lx-b هیچ چیزی چاپ نکرد و docker diff lx-b هم خالی است. فقط lx-a تغییر دارد (A /tmp/note.txt).

چرا؟ هر دو از یک image ساخته شده‌اند و لایه‌های image فقط‌خواندنی و مشترک‌اند. فایل جدید در لایه‌ی قابل‌نوشتن مخصوص lx-a نوشته شد، و lx-b لایه‌ی قابل‌نوشتن خودش را دارد که خالی است. کانتینرها از هم جدا هستند.

؟ آزمونک
  1. کانتینر دقیقاً چیست؟

  2. فرق image و container چیست؟

  3. در دستور «docker run -d -p 8099:80 nginx»، عدد 8099 مربوط به کجاست؟

  4. چرا کانتینر «docker run -d ubuntu:24.04» در docker ps دیده نمی‌شود؟

  5. اگر داخل یک کانتینر فایل بسازی و آن کانتینر را حذف کنی، چه می‌شود؟

  • داکر مشکل «روی سیستم من کار می‌کرد» را با بسته‌بندی برنامه همراه همه‌ی وابستگی‌هایش حل می‌کند.
  • Image قالب فقط‌خواندنی است، container نمونه‌ی در حال اجرای آن، و registry انبار image ها (مثل Docker Hub).
  • از بیرون: docker CLI با dockerd حرف می‌زند. از درون: containerd و runc با کمک namespace (جداسازی)، cgroup (محدودیت منابع) و لایه‌های فایل کانتینر را می‌سازند.
  • کانتینر یک پروسه است. وقتی پروسه‌ی اصلی تمام شود، کانتینر هم تمام می‌شود.
  • هر کانتینر یک لایه‌ی قابل‌نوشتن موقت دارد؛ با حذف کانتینر، آن داده‌ها هم می‌روند.
  • داکر روی مک و ویندوز داخل یک VM لینوکسی اجرا می‌شود (روی ویندوز، با WSL 2).
برگه‌ی تقلب این درس
دستورکاری که می‌کند
docker --versionنسخه‌ی docker CLI
docker versionنسخه‌ی CLI و daemon (Client و Server)
docker infoاطلاعات کلی daemon (هسته، runtime، ...)
docker run IMAGEساخت و اجرای کانتینر (و pull اگر image نباشد)
docker run -d -p 8099:80 --name NAME IMAGEاجرا در پس‌زمینه، با پورت و اسم
docker run --rm IMAGE CMDاجرای یک دستور و پاک شدن خودکار کانتینر
docker run --memory 100m IMAGEسقف حافظه برای کانتینر
docker psکانتینرهای در حال اجرا
docker ps -aهمه‌ی کانتینرها (حتی متوقف‌شده)
docker imagesimage های روی سیستم
docker logs NAMEلاگ کانتینر
docker top NAMEپروسه‌های داخل کانتینر
docker diff NAMEتغییرات لایه‌ی قابل‌نوشتن (A، C، D)
docker history IMAGEلایه‌های image و دستور ساخت هر کدام
docker image inspect IMAGEجزئیات کامل image (مثلاً تعداد لایه‌ها)
docker stop NAMEتوقف کانتینر
docker rm NAMEحذف کانتینر
docker rmi IMAGEحذف image

در درس بعد کانتینر را کنار ماشین مجازی می‌گذاریم و دقیق مقایسه‌شان می‌کنیم.