کدنامهمرجع‌های مهندسی نرم‌افزار، به فارسی
Docker · فصل ۲Docker · Chapter 2

نصب روی ویندوز، لینوکس و WSL2

Installing on Windows, Linux, and WSL2

این فصل قرار نیست فقط Docker را نصب کند و تمام. می‌خواهیم بفهمیم وقتی یک دستور ساده مثل docker ps جواب نمی‌دهد، دقیقاً کجای مسیر گیر کرده‌ایم؛ خود CLI؟ موتور Docker؟ دسترسی کاربر؟ یا ارتباط WSL با Docker Desktop؟

We are not merely installing Docker and trusting a green check mark. By the end of this chapter, when docker ps fails, you should know whether the likely boundary is the CLI, context, socket, daemon, WSL integration, or backend—and how to test each boundary with evidence.

۸۵دقیقهٔ مطالعه و اجراminutes
۱۸تمرین با پاسخsolved exercises
۴نمودار مفهومیdiagrams
۱آزمایشگاه عیب‌یابیtroubleshooting lab

وقتی docker ps می‌زنیم، پشت صحنه چه اتفاقی می‌افتد؟When we say “Docker is installed,” what exactly was installed?

فرض کن Docker را تازه نصب کرده‌ای. آیکن Desktop سبز است و همه‌چیز ظاهراً خوب به نظر می‌رسد. وارد ترمینال می‌شوی، docker ps را می‌زنی و خطا می‌گیری. اولین وسوسه این است که بگویی «پس Docker درست نصب نشده». اما هنوز برای چنین نتیجه‌ای زود است. شاید خود CLI سالم باشد و فقط نتواند به Docker Engine برسد. برای همین اول باید مسیر این دستور را بشناسیم.

In Chapter 1, Docker was a way to package and run reproducible environments. Now we need to separate the moving parts. When you type docker ps, the terminal itself knows nothing about containers. A client program called the Docker CLI runs, connects to an endpoint, and asks the Docker Engine for state.

PieceWhat it doesWhat failure often looks like
Shell / terminalبرنامهٔ docker را از مسیر پیدا و اجرا می‌کندfinds and launches the docker executable from PATHcommand not found
Docker CLIدستور و flagها را parse می‌کند و درخواست می‌سازدparses commands/flags and forms requestssyntax/usage خطاsyntax or usage error
Context / endpointمی‌گوید CLI به کدام Docker نقطهٔ اتصال وصل شودtells the CLI which Docker endpoint to useوصل‌شدن به daemon اشتباه یا unreachable نقطهٔ اتصالwrong daemon or unreachable endpoint
Docker Engine / dockerdوضعیت، چرخهٔ عمر، image/container و API را مدیریت می‌کندmanages API, state, images, and container lifecycleCannot connect to the Docker daemon
containerd / runtime stackکار اجرایی پایین‌تر را برای Engine انجام می‌دهدperforms lower-level runtime work for the Engineزمان اجرا/راه‌اندازی خطاruntime or startup failure
Linux kernelپردازش isolation، namespaces، cgroups و منابع را فراهم می‌کندprovides process isolation, namespaces, cgroups, and resourcesمعمولاً پشت خطاهای سطح بالاتر پنهان استusually surfaced through higher-level errors
Docker CLI request path shell: docker ps Docker CLI · parse / format active context / endpoint · Docker API dockerd / Docker Engine containerd / runtime stack Linux kernel request ↓ response ↑

فلش‌های رو به پایین مسیر درخواست را نشان می‌دهند؛ پاسخ در جهت مخالف برمی‌گردد. CLI خودش container را اجرا نمی‌کند؛ درخواست می‌فرستد و نتیجه را برای انسان قالب می‌کند.

Downward arrows show the request path; the response returns in the opposite direction. The CLI does not itself run the container; it sends the request and formats the result for a person.

از کجا بفهمیم دقیقاً کدام بخش سالم است؟Four commands that prove four different things

اینجا چهار دستور داریم که ظاهرشان شبیه هم است، ولی هرکدام چیز متفاوتی را به ما نشان می‌دهند. اگر فرقشان را بفهمی، بعداً به‌جای نصب دوباره و حدس‌زدن، با چند دستور ساده می‌فهمی مشکل از کجاست.

Many bad troubleshooting sessions begin with “Docker is installed because version works.” A better question is: which version command, and what exactly did it prove?

CommandWhat it provesWhat it does not prove
docker --versionفایل اجرایی محلی Docker CLI پیدا و اجرا می‌شودthe local Docker CLI executable is found and runsdaemon در دسترس استthe daemon is reachable
docker versionکلاینت محلی؛ و اگر سرور بخش آمد، API/Engine پاسخ دادهlocal Client; if Server appears, the API/Engine respondedبرنامه خاصی سالم استa particular application is healthy
docker infoاطلاعات عمیق‌تر Engine و اتصال موفق به سرورdeeper Engine facts and successful server communicationcontainer تو درست تنظیمات شدهyour container is correctly configured
docker run hello-worldEngine می‌تواند image را پیدا/در صورت نیاز دریافت کند، container بسازد، راه‌اندازی کند، خروجی بگیرد و خروج را ثبت کندthe Engine can resolve/pull if needed, create, start, capture output, and record container exitشبکه/volume/برنامه واقعی تو سالم استyour real app, network, or volume setup is healthy
verification ladder
docker --version
docker version
docker context show
docker info --format 'server={{.ServerVersion}} root={{.DockerRootDir}}'
docker ps
representative healthy output
Docker version 29.x, build 1234567

Client: Docker Engine - Community
 Version:           29.x
 Context:           default
Server: Docker Engine - Community
 Engine:
  Version:          29.x

default
server=29.x root=/var/lib/docker

CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

خالی بودن جدول docker ps خطا نیست؛ فقط یعنی running container نداریم. این تفاوت کوچک مهم است: دستور موفق بوده و Engine جواب داده، حتی اگر نتیجهٔ پرس‌وجو صفر ردیف باشد.

An empty docker ps table is not a failure; it simply means there are no running containers. The command still succeeded and the Engine answered even though the query returned zero rows.

یک بار موتور Docker را خاموش کنیم و نتیجه را ببینیمStop the daemon deliberately to see the Client/Server boundary

بهترین راه برای فهمیدن مرز بین CLI و Engine این است که آن را عمداً خراب کنیم. روی یک سیستم آزمایشی Linux، daemon را متوقف می‌کنیم و قبل از اجرای هر دستور حدس می‌زنیم کدام‌یک هنوز باید کار کند. بعد خروجی را با حدسمان مقایسه می‌کنیم.

On a learning Linux machine, one of the best ways to understand the architecture is to deliberately remove one layer. Before running anything, predict which commands should still work and which should fail.

Linux · deliberate daemon failure
sudo systemctl stop docker

docker --version
docker version
docker info
docker ps

sudo systemctl start docker
representative failure
Docker version 29.x, build 1234567

Client: Docker Engine - Community
 Version:           29.x
 Context:           default
Cannot connect to the Docker daemon at unix:///var/run/docker.sock.
Is the docker daemon running?

ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

این خروجی معماری را بهتر از تعریف حفظی نشان می‌دهد. docker --version اصلاً سرور را لمس نکرد. docker version توانست کلاینت محلی را بخواند ولی وقتی به سرور رسید ناموفق شد. info و ps بدون Engine پاسخ مفیدی ندارند.

This output teaches the architecture better than a memorized definition. docker --version never touched the Server. docker version could read the local Client but failed when it reached the Server. info and ps depend on an Engine response.

روی production این آزمایش را انجام ندهDo not perform this experiment on production

خاموش‌کردن daemon می‌تواند روی workloadهای واقعی اثر بگذارد. این آزمایش برای VM، لپ‌تاپ آموزشی یا محیطی است که می‌دانی container مهمی روی آن اجرا نمی‌شود.

Stopping the daemon can affect real workloads. Perform this only on a VM, a learning laptop, or an environment where you know no important containers depend on the daemon.

Docker Engine با Docker Desktop چه فرقی دارد؟Docker Engine and Docker Desktop are not the same thing

این دو اسم زیاد کنار هم می‌آیند و برای همین راحت قاطی می‌شوند. Docker Engine همان بخشی است که واقعاً image و container را مدیریت می‌کند. Docker Desktop یک محیط کامل‌تر برای توسعه است که همین Engine را همراه با رابط کاربری، تنظیم منابع و اتصال به محیط‌هایی مثل WSL در اختیارمان می‌گذارد.

Docker Engine is the server-side system that manages the API, daemon, runtime stack, images, and containers. Docker Desktop is a broader developer product that packages an Engine with integration, UI, resource management, updates, and development tooling.

EnvironmentTypical choiceWhy
Linux production/serverDocker Engineheadless، systemd، کنترل مستقیم سیستم میزبانheadless, systemd-managed, direct host control
Linux workstationEngine or Desktopبسته به نیاز به Desktop ابزارهاdepends on whether Desktop tooling is useful
Windows developerDocker Desktop + WSL2 backendLinux container بخش پشتی مدیریت‌شدهmanaged Linux-container backend
Windows + Ubuntu WSLDesktop + WSL integrationامکان استفاده از Linux CLI داخل توزیع و Windows CLI روی همان Desktop بخش پشتیLinux CLI in the distro and Windows CLI can reach the Desktop backend
Engine and Desktop relationship Docker CLIclient Docker DesktopUI · integration · resourcesmanaged Linux backendDocker Engine inside containersLinux workloads

Desktop «به‌جای Engine» نیست؛ Engine را به‌عنوان بخشی از یک محیط توسعهٔ مدیریت‌شده ارائه می‌کند.

Desktop is not “instead of Engine”; it provides an Engine as part of a managed development environment.

دو daemon بی‌دلیل نسازDo not create two daemons accidentally

اگر داخل Ubuntu/WSL یک Docker Engine جدا نصب کنی و همزمان Docker Desktop هم فعال باشد، ممکن است دو نقطهٔ اتصال و دو image/container مخزن مستقل داشته باشی. نتیجهٔ رایج: «image من کجا رفت؟» درحالی‌که فقط CLI به daemon دیگری نگاه می‌کند.

If you install a separate Docker Engine inside Ubuntu/WSL while Docker Desktop is also active, you can end up with two independent endpoints and image/container stores. The common symptom is “where did my image go?” when the CLI is simply looking at a different daemon.

نصب روی Ubuntu؛ هر دستور برای چه کاری است؟Ubuntu: do not see a command wall; understand the trust and package chain

اگر دستورهای نصب را فقط کپی کنی، دفعهٔ بعد که یکی از آن‌ها خطا بدهد نمی‌دانی باید کجا را نگاه کنی. پس به‌جای یک دیوار بلند از دستورها، نصب را به سه سؤال ساده می‌شکنیم: بسته‌ها را از کجا می‌گیریم؟ از کجا مطمئن می‌شویم منبع قابل‌اعتماد است؟ و در آخر دقیقاً چه چیزهایی نصب می‌شوند؟

The standard maintainable path is Docker’s official APT repository. The idea is simple: APT needs to know where packages come from, which key validates that source metadata, and which packages to install.

Ubuntu · official repository setup
sudo apt update
sudo apt install ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

URIs کد برنامه رسمی را مشخص می‌کند؛ Suites release فعلی Ubuntu را انتخاب می‌کند؛ Architectures معماری سیستم میزبان را می‌گیرد؛ و Signed-By می‌گوید فراداده این کد برنامه باید با همین key بررسی شود. این بخش security theater نیست؛ زنجیره of اعتماد package manager است.

URIs names the official source; Suites selects the current Ubuntu release; Architectures records host architecture; and Signed-By limits validation of this source to that key. This is not ceremony; it is the package manager’s trust chain.

Ubuntu · install packages
sudo apt install \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin
PackageRole in this courseUseful verification
docker-ceEngine / daemonEngine / daemonsystemctl status docker
docker-ce-cliDocker CLIdocker --version
containerd.ioزمان اجرا manager زیر Engineruntime manager beneath Engineاطلاعات در docker inforuntime facts in docker info
docker-buildx-pluginbuildهای مدرن؛ فصل ۴modern builds; Chapter 4docker buildx version
docker-compose-pluginCompose؛ موضوع فصل‌های بعدCompose; covered laterdocker compose version
service + verification
sudo systemctl status docker
sudo systemctl start docker   # only if it is not running

docker version
docker info
sudo docker run hello-world

اگر docker version فقط کلاینت را نشان داد، نصب CLI موفق بوده ولی هنوز سرور را ثابت نکرده‌ای. اگر sudo docker run hello-world موفق شد اما بدون sudo دسترسی denied گرفتی، دیگر مسئله installation نیست؛ مسئلهٔ دسترسی به سوکت است.

If docker version shows only Client information, the CLI installation succeeded but the Server is not yet proven. If sudo docker run hello-world works while the non-sudo command gets permission denied, the problem is no longer installation; it is socket access.

چرا با sudo کار می‌کند ولی بدون آن نه؟/var/run/docker.sock: a permission error can tell you a lot

این یکی از خطاهایی است که در نگاه اول آدم را به اشتباه می‌اندازد. ممکن است CLI نصب باشد، daemon هم روشن باشد، ولی کاربر فعلی اجازهٔ دسترسی به سوکتی را نداشته باشد که CLI از طریق آن با Docker حرف می‌زند. پس اینجا مسئله «نصب خراب» نیست؛ مسئله «اجازهٔ دسترسی» است.

On a typical Linux Docker Engine setup, the local CLI commonly talks to the daemon through a Unix socket. If the user cannot access that socket, the CLI may be perfectly healthy and the daemon may be running, yet the request still fails at the permission boundary.

permission diagnosis
docker ps
sudo docker ps
ls -l /var/run/docker.sock
id
representative evidence
permission denied while trying to connect to the Docker daemon socket

# sudo docker ps succeeds

srw-rw---- 1 root docker ... /var/run/docker.sock
uid=1000/alex gid=1000/alex groups=1000/alex,...

این مقایسه خیلی مهم‌تر از نصب دوباره کردن Docker است. اگر دستور معمولی دسترسی denied بدهد ولی همان دستور با sudo جواب بدهد، daemon و سوکت به‌احتمال زیاد حاضرند؛ credential کاربر معمولی اجازهٔ استفاده از سوکت را ندارد.

This comparison is far more informative than reinstalling Docker. If the ordinary command gets permission denied but the same command works with sudo, the daemon and socket are likely present; the ordinary user simply lacks socket access.

عضویت در docker گروه دسترسی کم‌خطر نیستMembership in the docker group is not low-risk access

Docker Docs صریحاً هشدار می‌دهد که docker گروه عملاً سطح بالایی از اختیار روی سیستم میزبان می‌دهد. پس «برای راحتی کاربر را به گروه اضافه کن» را مثل یک دسترسی کوچک توضیح نده. روی لپ‌تاپ توسعه تصمیم رایجی است؛ روی محیط حساس باید آگاهانه باشد.

Docker’s documentation explicitly warns that the docker group grants high privileges over the host. Do not describe “add the user to the group” as a trivial permission tweak. It is common on development machines, but it should be a deliberate security decision on sensitive systems.

optional non-root setup
sudo usermod -aG docker $USER
# sign out and back in, or start a new session
id
docker ps

روی Windows، Linux container از کجا Linux می‌آورد؟Why Windows needs a Linux kernel for Linux containers

اگر container لینوکسی اجرا می‌کنیم، یک سؤال طبیعی پیش می‌آید: روی Windows که هستهٔ Linux نداریم، این container دقیقاً روی چه چیزی اجرا می‌شود؟ پاسخ را باید در WSL2 پیدا کنیم. WSL2 یک هستهٔ واقعی Linux در اختیار Windows می‌گذارد و Docker Desktop از همین بستر برای اجرای containerهای لینوکسی استفاده می‌کند.

Linux containers rely on Linux-kernel system calls and isolation features. The Windows kernel does not natively provide the same interface. WSL2 matters because it supplies a real managed Linux kernel that Docker Desktop can use for its Linux-container backend.

ThingWhat it isWhat it is not
Windows hostسیستم‌عامل اصلی و محیط Desktop/PowerShellmain OS and Desktop/PowerShell environmentLinux containera Linux container
WSL2پلتفرم اجرای محیط‌های Linux با Linux هستهٔ لینوکسplatform for Linux environments backed by a Linux kernelخود Docker EngineDocker Engine itself
Ubuntu WSL distroworkspace لینوکسی کاربر با سیستم‌فایل و شل خودشa user Linux workspace with its own filesystem and shellDocker container یا لزوماً daemon Dockera Docker container or necessarily a Docker daemon
docker-desktop environmentمحیط مدیریت‌شدهٔ Docker Desktop برای بخش پشتی خودشDocker Desktop’s managed backend environmentUbuntu روزمرهٔ توyour everyday Ubuntu distro
Docker containerprocessهای ایزوله‌شده‌ای که Engine lifecycleشان را مدیریت می‌کندisolated processes whose lifecycle is managed by the Engineیک WSL توزیع کاملa full WSL distribution

PowerShell و Ubuntu دو راه جدا برای رسیدن به یک Docker هستندPowerShell and Ubuntu/WSL are two client paths, not one magical route

فرض کن در PowerShell دستور docker ps کاملاً کار می‌کند، اما همان دستور داخل Ubuntu خطا می‌دهد. این عجیب نیست. PowerShell و Ubuntu دو محیط جدا هستند و هرکدام CLI و مسیر اتصال خودشان را دارند. ممکن است هر دو در نهایت به همان Docker Engine برسند، اما راه رسیدنشان یکی نیست.

This is where a misleading diagram can do more damage than a weak paragraph. The Windows CLI and the Linux CLI inside Ubuntu are different executables in different environments. Both can reach Docker Desktop’s backend, but they do not follow an identical path. WSL Integration matters for the Linux distribution’s access; PowerShell should not be modeled as passing through a generic “WSL Integration layer.”

Windows and WSL client paths to Docker Desktop Engine PowerShellWindows environment Windows Docker CLIDesktop endpoint/context Ubuntu / WSL2Linux environment Linux Docker CLIWSL integration path Docker Desktop backendDocker API / Enginemanaged Linux environment

فلش‌ها درخواست مسیر را نشان می‌دهند. دو کلاینت مسیر در بخش پشتی/Engine همگرا می‌شوند؛ WSL یکپارچه‌سازی مخصوص مسیر توزیع لینوکسی است، نه یک API عمومی برای هر دو سمت.

The arrows represent request paths. The two clients converge at the backend/Engine; WSL Integration belongs to the Linux-distribution path rather than acting as one generic API layer for both sides.

Windows prerequisites
wsl --version
wsl -l -v

در wsl -l -v ستون نسخه برای توزیع مورد استفاده باید 2 باشد. Running یا Stopped وضعیت فعلی توزیع است؛ با WSL نسخه یکی نیست.

In wsl -l -v, the VERSION column should show 2 for the distribution you intend to integrate. Running or Stopped is the distro’s current state, not its WSL architecture version.

از کجا مطمئن شویم هر دو ترمینال همان Engine را می‌بینند؟How do we prove PowerShell and Ubuntu are really seeing the same Engine?

فقط اینکه هر دو جا یک شماره نسخه ببینی کافی نیست. دو Engine جدا هم می‌توانند دقیقاً یک نسخه داشته باشند. راه مطمئن‌تر این است که در یکی از ترمینال‌ها چیزی بسازیم و در دیگری همان مورد را با همان شناسه پیدا کنیم. اگر این اتفاق افتاد، دیگر فقط به شباهت خروجی‌ها تکیه نکرده‌ایم.

Matching Server Version strings are not conclusive proof. Two independent Engines can run the same version. A stronger test is to create shared state on one side and observe that exact object from the other.

PowerShell · create evidence
docker context show
docker info --format 'name={{.Name}} root={{.DockerRootDir}} server={{.ServerVersion}}'
docker run -d --name engine-proof nginx:alpine
docker inspect engine-proof --format '{{.Id}}'
Ubuntu / WSL · observe the same object
docker context show
docker info --format 'name={{.Name}} root={{.DockerRootDir}} server={{.ServerVersion}}'
docker ps --filter name=engine-proof
docker inspect engine-proof --format '{{.Id}}'

اگر همان container name و همان container شناسه را از هر دو طرف می‌بینی، مدرک خیلی قوی‌تری داری که هر دو کلاینت به یک Docker وضعیت رسیده‌اند. بعد از آزمایش:

If both sides see the same container name and the same container ID, you have much stronger evidence that both clients reached the same Docker state. Clean up afterward:

cleanup
docker rm -f engine-proof

hello-world فقط پیام تبریک نیستDo not treat hello-world as a congratulation message; read its trace

اولین بار که hello-world را اجرا می‌کنی، Docker چند کار را پشت سر هم انجام می‌دهد: image را پیدا می‌کند، اگر لازم باشد آن را می‌گیرد، container را می‌سازد، اجرا می‌کند، خروجی را نشان می‌دهد و پایان پردازش را ثبت می‌کند. پس همین مثال کوچک در واقع یک آزمایش کامل برای مسیر اجراست.

If the image is absent locally, the first docker run hello-world exercises several stages: local lookup, pull if needed, create, start, stdout, and exit. If a second run does not pull, that does not invalidate the test; the image is probably already in the local store.

practical verification
docker run hello-world
docker ps
docker ps -a --filter ancestor=hello-world

در فصل بعد همین اتفاق را آهسته‌تر باز می‌کنیم: چرا container در ps نیست ولی در ps -a دیده می‌شود، و چه چیزی باعث توقف آن شد.

Chapter 3 will slow this down: why the container disappears from ps yet remains in ps -a, and what caused it to stop.

وقتی خطا می‌بینی، از کجا شروع کنی؟Troubleshooting means naming the broken layer before choosing a fix

فرض کن فقط این جمله را می‌شنوی: «Docker کار نمی‌کند.» این هنوز هیچ چیزی به ما نمی‌گوید. باید خطا را مرحله‌به‌مرحله کوچک کنیم: آیا دستور docker پیدا می‌شود؟ آیا CLI به Engine وصل می‌شود؟ آیا مشکل دسترسی داریم؟ آیا روی Windows، WSL درست به Desktop متصل شده؟ هر جواب، چند احتمال را کنار می‌زند.

An error string is not a complete diagnosis; it is an observation. A strong flow is: symptom → suspected layer → diagnostic command → fix → verification.

Docker installation troubleshooting flow symptomwhat happened? layerwhere? evidencetest it fixtarget layer verifyprove

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

Restarting everything may temporarily remove a symptom, but it teaches little. A diagnostic command should test the specific hypothesis you have.

SymptomLikely boundaryEvidence → fix → verify
docker: command not foundshell / PATH / CLIcommand -v docker → install/fix PATH → docker --version
Cannot connect to the Docker daemoncontext / endpoint / daemondocker context show + service/Desktop status → fix target/daemon → docker info
permission denied ... docker.socklocal socket permissionsudo docker ps + ls -l /var/run/docker.sock → deliberate access fix → normal docker ps
PowerShell works, Ubuntu says command not foundWSL distro client pathcommand -v docker + WSL Integration → enable/fix distro path → docker info in Ubuntu
PowerShell works, Ubuntu cannot reach daemonWSL integration / context / backendwsl -l -v + Desktop WSL Integration + docker context show → fix integration → shared-state test
“my images disappeared”wrong Engine/context/storedocker context ls + formatted docker info → select expected Engine → docker image ls

شش دام که ظاهرشان شبیه «Docker خراب است» استSix traps that all look like “Docker is broken”

۱. docker --version را سلامت کامل فرض‌کردن1. Treating docker --version as full health

این فقط کلاینت فایل اجرایی را ثابت می‌کند. برای سرور به docker version سرور بخش یا docker info نیاز داری.

It proves only the Client executable. Use the Server section of docker version or docker info to prove Engine communication.

۲. هر دسترسی خطا را با نصب دوباره جواب‌دادن2. Reinstalling for every permission error

اگر sudo موفق است و کاربر عادی ناموفق می‌شود، اول سوکت صاحب/گروه و کاربر groups را ببین. نصب دوباره معمولاً این مرز را حل نمی‌کند.

If sudo succeeds while the ordinary user fails, inspect socket ownership and group membership first. Reinstallation normally does not fix that boundary.

۳. Ubuntu WSL را container فرض‌کردن3. Treating Ubuntu WSL as a container

Ubuntu WSL یک Linux کاربر environment است؛ container را Docker Engine می‌سازد و چرخهٔ عمر متفاوتی دارد.

Ubuntu WSL is a Linux user environment; a container is created and managed by Docker Engine with a different lifecycle.

۴. WSL یکپارچه‌سازی را مسیر PowerShell هم تصورکردن4. Modeling WSL Integration as PowerShell’s path too

Windows CLI و Linux CLI مسیرهای کلاینت متفاوتی دارند. هر دو ممکن است به بخش پشتی مشترک برسند، اما یکپارچه‌سازی مربوط به توزیع لینوکسی است.

Windows and Linux CLIs follow different client paths. Both may reach the same backend, but WSL Integration belongs to the Linux-distribution path.

۵. نسخه مشابه را اثبات یک Engine دانستن5. Treating matching versions as proof of one Engine

مشترک وضعیت را امتحان کن: مورد منحصربه‌فرد بساز و از ترمینال دیگر همان شناسه را ببین.

Test shared state: create a uniquely identifiable object and observe the same ID from the other terminal.

۶. راه‌اندازی دوباره را جای تشخیص گذاشتن6. Replacing diagnosis with restart

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

A restart is sometimes appropriate, but capture the error and boundary first. Otherwise you may only erase the symptom without learning how to diagnose it next time.

روی Ubuntu فقط دنبال کلمهٔ active نگردDo not stop at “systemd is green”; read what the service status tells you

وقتی روی Ubuntu می‌خواهی ببینی daemon واقعاً بالا آمده یا نه، systemctl status docker مثل یک برگهٔ وضعیت کوتاه است. فقط به سبز بودن active نگاه نکن؛ همان چند خط به تو می‌گوید سرویس شناخته شده یا نه، الآن در چه وضعیتی است و پردازش اصلی‌اش کدام است.

On a typical Ubuntu host, systemctl status docker is one of the best places to see whether the daemon became a running process at all. But if you only look for the word active, you throw away most of the useful evidence.

service state
sudo systemctl status docker --no-pager

● docker.service - Docker Application Container Engine
     Loaded: loaded (...; enabled; preset: enabled)
     Active: active (running) since ...
   Main PID: 2148 (dockerd)
      Tasks: ...
     Memory: ...
        CPU: ...
     CGroup: /system.slice/docker.service
             └─2148 /usr/bin/dockerd -H fd:// ...

Loaded می‌گوید unit شناخته شده است؛ enabled بیشتر دربارهٔ boot/راه‌اندازی سیاست است، نه اینکه همین لحظه پردازش سالم باشد. Active: active (running) وضعیت فعلی را می‌دهد و Main PID نشان می‌دهد systemd کدام پردازش را daemon اصلی می‌داند.

Loaded says the unit is known; enabled is mainly about boot/start policy, not proof that a healthy process exists right now. Active: active (running) gives current state, and Main PID identifies the daemon process systemd is managing.

اگر وضعیت برابر ناموفق باشد، فقط راه‌اندازی دوباره نزن. اول logهای نزدیک خطا را بخوان:

If status is failed, do not immediately restart and erase the moment. Read recent service logs first:

service logs
sudo journalctl -u docker -n 60 --no-pager

هدف این نیست که تمام logهای dockerd را بلد باشی؛ دنبال اولین خطا معناداری بگرد که زنجیره خطا را شروع کرده. ده خط بعدی ممکن است فقط پیامد همان خط اول باشند.

You do not need to memorize every dockerd log message. Look for the first meaningful error that began the failure chain; many later lines may be consequences rather than the cause.

گاهی Docker خراب نیست؛ فقط داری با Engine اشتباهی حرف می‌زنیDocker context: when the command is correct but the target Engine is wrong

فرض کن دیروز یک image ساخته‌ای و امروز هرچه docker image ls می‌زنی پیدایش نمی‌کنی. قبل از اینکه دوباره build کنی، یک احتمال ساده را بررسی کن: شاید CLI امروز به Engine دیگری وصل است. در این حالت چیزی گم نشده؛ فقط مقصد دستورهایت عوض شده.

Sometimes nothing is actually broken. The CLI works, the daemon works, but the CLI is pointed at a different Engine. This matters especially with Desktop, remote Engines, or multiple installations.

context inspection
docker context ls
docker context show
docker info --format \
'name={{.Name}} root={{.DockerRootDir}} server={{.ServerVersion}}'

این اتفاق وقتی چند context، Docker Desktop یا یک Engine راه‌دور داری کاملاً ممکن است. پس قبل از هر نصب دوباره یا build دوباره، اول ببین CLI واقعاً به کجا وصل شده است.

Suppose you built an image while context A was active. Later the active context becomes B and docker image ls no longer shows it. A weak response is to pull/build again. A better response is to verify the destination first; duplicating the artifact can merely hide a targeting mistake.

یک سؤال قبل از هر نصب دوبارهOne question before reinstalling

«آیا همان کلاینت به همان endpointی که فکر می‌کنم وصل است؟» اگر هنوز جواب این سؤال را نداری، نصب دوباره احتمالاً زود است.

“Is this client actually connected to the endpoint I think it is?” If you cannot answer that yet, reinstalling is probably premature.

روی Windows هر دو سمت را جدا امتحان کنOn Windows, one green check is not enough; verify each client path separately

سبز بودن Docker Desktop فقط می‌گوید خود Desktop ظاهراً بالا است. هنوز معلوم نیست PowerShell و Ubuntu هر دو بتوانند از مسیر خودشان به آن برسند. برای همین هر محیطی را که واقعاً با آن کار می‌کنی جدا بررسی کن.

Docker Desktop can be Running and PowerShell fully functional while the Ubuntu/WSL client path is still broken. The reverse can also happen. Verify every environment you actually plan to use for development.

PowerShell
wsl -l -v
docker context show
docker version
docker info --format 'server={{.ServerVersion}}'
Ubuntu / WSL
command -v docker
docker context show
docker version
docker info --format 'server={{.ServerVersion}}'

اول در PowerShell مطمئن شو CLI و Engine همدیگر را می‌بینند. بعد همان بررسی را داخل Ubuntu انجام بده. اگر هر دو سالم بودند، تازه می‌توانیم با یک container مشترک بررسی کنیم که واقعاً به یک Engine وصل‌اند.

These checks answer two different questions: does the Windows CLI path work, and does the Linux-distro CLI path work? If both do, the shared-state test can then prove whether they converge on the same Engine.

چرا «Desktop باز است» مدرک کافی نیست؟

Why is “Desktop is open” insufficient evidence?

چون UI وضعیت فقط یک بخش از زنجیره را می‌بیند. شل ممکن است Docker CLI را پیدا نکند؛ توزیع ممکن است WSL1 باشد؛ یکپارچه‌سازی ممکن است برای توزیع دیگری فعال باشد؛ یا context CLI به مقصد دیگری اشاره کند. عیب‌یابی خوب دقیقاً همین مرزها را جدا می‌کند.

Because UI status observes only part of the chain. The shell may not find a Docker CLI, the distro may be WSL1, integration may be enabled for another distro, or the CLI context may target something else. Good troubleshooting separates these boundaries.

یک نمونهٔ واقعی: PowerShell کار می‌کند، Ubuntu نهCase study: “it works in PowerShell, not in Ubuntu”

فرض کن همکارت می‌گوید: «Docker Desktop بازه، توی PowerShell همه‌چی کار می‌کنه، ولی توی Ubuntu هرچی docker ps می‌زنم خطا می‌گیرم.» اینجا اگر بی‌درنگ Docker را داخل Ubuntu نصب کنیم، ممکن است فقط مسئله را پیچیده‌تر کنیم. اول قدم‌به‌قدم می‌بینیم مسیر Ubuntu کجا قطع شده.

Treat this like a real support ticket. The initial report is only: “Docker Desktop is running. docker ps works in PowerShell. Ubuntu fails.” Do not fix yet; narrow the chain first.

Step 1 · prove the distro architecture
wsl -l -v

NAME      STATE     VERSION
Ubuntu    Running   2

نسخه=2 یک احتمال را حذف می‌کند: مشکل «این توزیع هنوز WSL1 است» نیست.

VERSION=2 removes one hypothesis: this is not a “the distro is still WSL1” problem.

Step 2 · does Ubuntu even have a usable CLI path?
command -v docker
/usr/bin/docker

docker --version
Docker version 29.x, build ...

پس شل و کلاینت فایل اجرایی سالم‌اند. اگر خطا هنوز Cannot connect... است، دیگر مسیر را دست‌کاری نمی‌کنیم؛ یک لایه پایین‌تر می‌رویم.

So the shell and Client executable are healthy. If the error is still Cannot connect..., PATH is no longer our target; move one boundary deeper.

Step 3 · target and integration
docker context show
docker info

# then verify Docker Desktop:
# Settings → Resources → WSL Integration → Ubuntu enabled

اگر یکپارچه‌سازی برای Ubuntu خاموش بوده و با فعال‌کردنش docker info سرور اطلاعات می‌دهد، راه‌حل و تشخیص با هم جورند: Linux کلاینت مسیر به بخش پشتی وصل نبود. لازم نبود Engine را داخل Ubuntu نصب کنیم.

If Ubuntu integration was disabled and enabling it makes docker info return Server facts, the fix matches the diagnosis: the Linux client path was not connected to the backend. Installing another Engine inside Ubuntu was unnecessary.

مرحلهٔ آخر مشترک-وضعیت آزمایش است. از PowerShell engine-proof را بساز و از Ubuntu همان شناسه را ببین. حالا گزارش فقط «درست شد» نیست؛ می‌گوید چه لایه‌ای خراب بود و چه چیزی recovery را ثابت کرد.

The final step is the shared-state test. Create engine-proof from PowerShell and observe the same ID from Ubuntu. The report is no longer “it works now”; it explains which boundary failed and what proved recovery.

۱۸ تمرین؛ این‌بار جواب را از روی نشانه‌ها پیدا کن18 exercises: from “is it installed?” to “which layer failed?”

قبل از اینکه پاسخ هر تمرین را باز کنی، یک حدس کوتاه بزن و بگو با کدام دستور می‌خواهی آن را بررسی کنی. قرار نیست فقط اسم دستورها را حفظ کنیم؛ می‌خواهیم از روی چیزی که می‌بینیم بفهمیم مشکل کجاست.

The final exercises deliberately preserve the same depth as the beginning of the chapter. Before revealing a solution, write a prediction or hypothesis.

حل‌شدهSolved۰ / ۱۸
تمرین ۲٫1 · Exercise 2.1مقدماتی · Beginner۴ min

daemon خاموش است. خروجی docker --version، docker version و docker info را پیش‌بینی کن.

The daemon is stopped. Predict docker --version, docker version, and docker info.

پاسخ و دلیل · Solution and reasoning

docker --version باید نسخهٔ کلاینت فایل اجرایی را بدهد. docker version کلاینت را چاپ می‌کند ولی سرور بخش ناموفق می‌شود. docker info برای اطلاعات اصلی سرور به daemon نیاز دارد و خطا می‌دهد.

docker --version should still print the local Client executable version. docker version prints Client information but its Server section fails. docker info depends on the daemon for its main Engine facts and errors.

دام: دیدن کلاینت خروجی در docker version را اتصال موفق به daemon تعبیر نکن.

Trap: do not interpret Client output in docker version as proof of a successful daemon connection.

تمرین ۲٫2 · Exercise 2.2مقدماتی · Beginner۴ min

command not found و Cannot connect to the Docker daemon چرا دو خطا کاملاً متفاوت‌اند؟

Why are command not found and Cannot connect to the Docker daemon fundamentally different failures?

پاسخ و دلیل · Solution and reasoning

اولی قبل از اجرای CLI رخ می‌دهد: شل فایل اجرایی را پیدا نکرده. دومی یعنی CLI اجرا شده ولی نقطهٔ اتصال/daemon جواب نداده. بنابراین نصب دوباره daemon برای خطا اول یا تغییر مسیر برای خطا دوم ممکن است کاملاً بی‌ربط باشد.

The first happens before the CLI runs: the shell cannot find the executable. The second means the CLI ran but the endpoint/daemon did not answer. Reinstalling the daemon for the first or changing PATH for the second may be completely irrelevant.

تمرین ۲٫3 · Exercise 2.3مقدماتی · Beginner۴ min

در docker version کدام بخش واقعاً پاسخ daemon را ثابت می‌کند؟

Which part of docker version actually proves a daemon response?

پاسخ و دلیل · Solution and reasoning

بخش Server: و اطلاعات زیر آن. کلاینت بخش محلی است. برای کامل‌تر شدن، docker context show را هم کنار آن بخوان تا بدانی کلاینت تلاش کرده به کدام context وصل شود.

The Server: section and its details. The Client section is local. Pair it with docker context show to see which context the Client attempted to use.

تمرین ۲٫4 · Exercise 2.4مقدماتی · Beginner۴ min

چرا Docker Desktop را نمی‌شود فقط «GUI برای Docker» تعریف کرد؟

Why is “a GUI for Docker” an incomplete definition of Docker Desktop?

پاسخ و دلیل · Solution and reasoning

چون Desktop علاوه بر UI، Engine/بخش پشتی مدیریت‌شده، یکپارچه‌سازی، مدیریت منابع، به‌روزرسانی‌ها و ابزارها توسعه را هم فراهم می‌کند. مخصوصاً روی Windows، همین بخش پشتی لینوکسی بخش مهم ماجراست.

Because Desktop provides more than UI: it manages an Engine/backend, integration, resources, updates, and developer tooling. On Windows in particular, the managed Linux backend is central.

تمرین ۲٫5 · Exercise 2.5تمرین · Practice۵ min

Ubuntu نصب commandها را به سه مفهوم تقسیم کن: اعتماد، کد برنامه و package.

Group the Ubuntu installation commands into three concepts: trust, source, and package.

پاسخ و دلیل · Solution and reasoning

keyring و Signed-By بخش اعتماد هستند؛ docker.sources کد برنامه/repository را تعریف می‌کند؛ و apt install docker-ce ... packageها را نصب می‌کند. این تقسیم باعث می‌شود خطا signature را با خطا package-not-found قاطی نکنی.

The keyring and Signed-By form the trust piece; docker.sources defines the source/repository; and apt install docker-ce ... installs packages. This prevents you from confusing signature failures with package-resolution failures.

تمرین ۲٫6 · Exercise 2.6تمرین · Practice۵ min

docker ps دسترسی denied می‌دهد ولی sudo docker ps موفق است. چه چیزی را همین حالا می‌دانی؟

docker ps gets permission denied but sudo docker ps succeeds. What do you already know?

پاسخ و دلیل · Solution and reasoning

می‌دانی CLI قابل‌اجراست و daemon/سوکت احتمالاً حاضرند؛ تفاوت credential بین کاربر معمولی و root مرز مسئله را به دسترسی نزدیک می‌کند. حالا ls -l /var/run/docker.sock و id شواهد بعدی‌اند.

You know the CLI runs and the daemon/socket are likely present; the difference between ordinary-user and root credentials points toward a permission boundary. ls -l /var/run/docker.sock and id are the next useful observations.

تمرین ۲٫7 · Exercise 2.7تمرین · Practice۵ min

چرا اضافه‌کردن کاربر به docker گروه را نباید «فقط رفع دسترسی» توضیح داد؟

Why should adding a user to the docker group not be described as “just fixing permission”?

پاسخ و دلیل · Solution and reasoning

چون دسترسی Docker API می‌تواند اختیار بسیار بالایی روی سیستم میزبان بدهد. این تصمیم برای لپ‌تاپ توسعه رایج است، اما پیامد امنیتی دارد و باید آگاهانه گرفته شود.

Because access to the Docker API can grant very high control over the host. It is common on a development laptop, but it has security implications and should be deliberate.

تمرین ۲٫8 · Exercise 2.8تمرین · Practice۵ min

wsl -l -v برای Ubuntu مقدار نسخه=2 و وضعیت=Stopped نشان می‌دهد. آیا این توزیع WSL1 است؟

wsl -l -v shows VERSION=2 and STATE=Stopped for Ubuntu. Is this a WSL1 distro?

پاسخ و دلیل · Solution and reasoning

نه. نسخه=2 معماری WSL2 را نشان می‌دهد؛ Stopped فقط وضعیت فعلی توزیع است. با اجراشدن Ubuntu می‌تواند Running شود بدون اینکه نسخه عوض شود.

No. VERSION=2 identifies WSL2 architecture; Stopped is only the distro’s current state. Starting Ubuntu can change state to Running without changing the version.

تمرین ۲٫9 · Exercise 2.9تمرین · Practice۵ min

یک تفاوت بنیادی بین Ubuntu در WSL و Docker container بنویس.

State one fundamental difference between Ubuntu in WSL and a Docker container.

پاسخ و دلیل · Solution and reasoning

Ubuntu WSL یک کاربر Linux environment با سیستم‌فایل و شل و چرخهٔ عمر خودش است؛ container یک زمان اجرا مورد است که Docker Engine از image می‌سازد و چرخهٔ عمر پردازش آن را مدیریت می‌کند.

Ubuntu WSL is a user Linux environment with its own filesystem, shell, and lifecycle; a container is a runtime object created from an image and lifecycle-managed by Docker Engine.

تمرین ۲٫10 · Exercise 2.10تمرین · Practice۵ min

PowerShell و Ubuntu هر دو Server Version: 29.x نشان می‌دهند. آیا این اثبات یک Engine است؟

PowerShell and Ubuntu both show Server Version: 29.x. Is that proof of one Engine?

پاسخ و دلیل · Solution and reasoning

نه؛ دو Engine جدا هم می‌توانند نسخهٔ یکسان داشته باشند. اثبات بهتر مشترک وضعیت است: یک container منحصربه‌فرد در یکی بساز و همان شناسه را در دیگری inspect کن.

No; two independent Engines can run the same version. A stronger test is shared state: create a uniquely named container from one client and inspect the same ID from the other.

تمرین ۲٫11 · Exercise 2.11تمرین · Practice۵ min

PowerShell کار می‌کند ولی داخل Ubuntu می‌گیری docker: command not found. آیا بخش پشتی خراب است؟

PowerShell works, but Ubuntu says docker: command not found. Is the backend necessarily broken?

پاسخ و دلیل · Solution and reasoning

نه. خطا هنوز در شل/CLI مسیر داخل Ubuntu است. اول command -v docker و WSL یکپارچه‌سازی را بررسی کن. بخش پشتی مشترک ممکن است کاملاً سالم باشد.

No. The failure is still at the Ubuntu shell/CLI path. Check command -v docker and WSL Integration first. The shared backend may be perfectly healthy.

تمرین ۲٫12 · Exercise 2.12تمرین · Practice۵ min

اگر Engine دوم داخل WSL نصب کنی، «imageها گم شده‌اند» چطور ایجاد می‌شود؟

How can installing a second Engine inside WSL create the illusion that “my images disappeared”?

پاسخ و دلیل · Solution and reasoning

هر daemon مخزن و نقطهٔ اتصال خودش را دارد. اگر CLI یک بار به Desktop Engine و بار دیگر به توزیع-محلی Engine وصل شود، هرکدام مجموعه متفاوتی از image/container می‌بینند؛ چیزی حذف نشده، فقط مقصد عوض شده است.

Each daemon owns its own endpoint and store. If the CLI points to Desktop Engine in one session and a distro-local Engine in another, the visible image/container sets differ; nothing necessarily disappeared—the destination changed.

تمرین ۲٫13 · Exercise 2.13سناریو · Scenario۶ min

Docker Desktop باز است، PowerShell سالم است، Ubuntu Cannot connect... می‌دهد. یک ترتیب تشخیص بنویس.

Docker Desktop is open, PowerShell works, but Ubuntu gets Cannot connect.... Write a diagnostic order.

پاسخ و دلیل · Solution and reasoning

۱) wsl -l -v و نسخه=2؛ ۲) توزیع درست؛ ۳) Settings → Resources → WSL یکپارچه‌سازی برای همان توزیع؛ ۴) داخل Ubuntu، command -v docker و docker context show؛ ۵) docker info. بعد از تغییر یکپارچه‌سازی، راه‌اندازی دوباره WSL/Desktop می‌تواند بررسی مرحله باشد، نه ritual اول کار.

1) verify VERSION=2 with wsl -l -v; 2) confirm the intended distro; 3) verify Docker Desktop WSL Integration for that distro; 4) inside Ubuntu check command -v docker and docker context show; 5) run docker info. After changing integration, restarting WSL/Desktop can be a verification/reset step rather than the first ritual.

تمرین ۲٫14 · Exercise 2.14سناریو · Scenario۶ min

بعد از systemctl stop docker، docker --version هنوز جواب می‌دهد. آیا توقف ناموفق بوده؟

After systemctl stop docker, docker --version still works. Did the stop fail?

پاسخ و دلیل · Solution and reasoning

نه؛ این دقیقاً انتظار ماست. docker --version فقط محلی CLI فایل اجرایی را می‌خواند. برای اثبات توقف، systemctl status docker و خطا در سرور-dependent دستورها مثل docker info را ببین.

No; that is exactly expected. docker --version only reads the local CLI executable. Prove the stop with systemctl status docker and failures in Server-dependent commands such as docker info.

تمرین ۲٫15 · Exercise 2.15سناریو · Scenario۶ min

hello-world در اجرای دوم دیگر دریافت نمی‌کند. آیا بررسی ناقص شده؟

hello-world does not pull on the second run. Is verification now incomplete?

پاسخ و دلیل · Solution and reasoning

نه. محلی image lookup این بار hit شده است. Engine هنوز container می‌سازد، راه‌اندازی می‌کند، stdout را می‌گیرد و خروج را ثبت می‌کند. اگر می‌خواهی دریافت مسیر را جدا تست کنی، آن یک سؤال دیگر است.

No. The local image lookup hit this time. The Engine still creates and starts a container, captures stdout, and records exit. Testing the pull path specifically is a separate question.

تمرین ۲٫16 · Exercise 2.16سناریو · Scenario۶ min

یک teammate می‌گوید «Docker خراب بود، راه‌اندازی دوباره کردم درست شد.» چه اطلاعاتی هنوز کم است؟

A teammate says, “Docker was broken; I restarted it and it worked.” What information is still missing?

پاسخ و دلیل · Solution and reasoning

نشانه اولیه، exact خطا، فعال context، سرویس/بخش پشتی وضعیت و بررسی بعد از راه‌حل. بدون این‌ها نمی‌دانیم راه‌اندازی دوباره واقعاً علت را حل کرده یا فقط وضعیت موقتی را بازنشانی کرده است.

The original symptom, exact error, active context, service/backend state, and post-fix verification are missing. Without them, we cannot tell whether the restart fixed the cause or merely reset transient state.

تمرین ۲٫17 · Exercise 2.17سناریو · Scenario۷ min

در Ubuntu، docker ps دسترسی denied است؛ sudo docker ps موفق؛ اما کاربر از قبل در docker گروه است. قدم بعدی چیست؟

In Ubuntu, docker ps gets permission denied; sudo docker ps succeeds; the user was already added to the docker group. What next?

پاسخ و دلیل · Solution and reasoning

با id بررسی کن نشست فعلی واقعاً عضویت جدید را دارد یا نه. گروه change معمولاً به ورود/نشست تازه نیاز دارد. بعد سوکت گروه/mode را با ls -l /var/run/docker.sock ببین. «قبلاً usermod زدم» مدرک نشست فعلی نیست.

Use id to verify that the current session actually includes the new group membership. Group changes commonly require a fresh login/session. Then inspect socket group/mode with ls -l /var/run/docker.sock. “I ran usermod earlier” is not evidence for the current session.

تمرین ۲٫18 · Exercise 2.18سناریو · Scenario۷ min

یک گزارش کوتاه بنویس که ثابت کند Windows CLI و Ubuntu CLI به یک Engine می‌رسند؛ فقط نسخه string کافی نیست.

Write a short report that proves the Windows CLI and Ubuntu CLI reach the same Engine; matching version strings are not enough.

پاسخ و دلیل · Solution and reasoning

نمونهٔ گزارش: در هر دو ترمینال context و قالب‌بندی‌شده info را ثبت کردم. از PowerShell یک container با نام engine-proof ساختم و شناسه آن را گرفتم. داخل Ubuntu همان name و همان شناسه را با docker ps/docker inspect دیدم. این مشترک مورد نشان می‌دهد هر دو کلاینت به یک Docker وضعیت رسیده‌اند. سپس container را پاک کردم.

Example report: I recorded context and formatted Engine info from both terminals. From PowerShell I created a container named engine-proof and captured its ID. From Ubuntu I found the same name and same ID using docker ps/docker inspect. The shared object shows both clients reached the same Docker state. I then removed the container.

آزمایشگاه: ثابت کن سیستم واقعاً برای کار آماده استLab: prove the machine is ready, not merely that Docker is installed

حدود ۳۵ دقیقهabout 35 minutes

فرض کن یک لپ‌تاپ تازه دستت رسیده و باید به نفر بعدی تحویلش بدهی. نوشتن «Docker نصب شد» کافی نیست. باید طوری بررسی‌اش کنی که اگر فردا مشکلی پیش آمد، معلوم باشد CLI، Engine، دسترسی و در صورت استفاده از Windows، مسیر WSL همگی واقعاً امتحان شده‌اند.

Scenario: you received a fresh laptop. You are not allowed to send a Docker Desktop screenshot and call it “ready.” Build an evidence bundle another engineer can follow.

  1. محیط را شناسایی کنIdentify the environment

    Linux یا Windows+WSL2؟ اگر Windows است، wsl --version و wsl -l -v را ثبت کن.

    Linux or Windows+WSL2? On Windows, record wsl --version and wsl -l -v.

  2. کلاینت و سرور را جدا ثابت کنProve client and server separately

    docker --version، docker version، docker context show و docker info را با یک جملهٔ تفسیر برای هرکدام ذخیره کن.

    Capture docker --version, docker version, docker context show, and docker info, with one sentence interpreting each.

  3. یک برنامه واقعی کوچک اجرا کنRun one real small workload

    docker run hello-world و بعد docker ps -a را بخوان.

    Run docker run hello-world and then inspect docker ps -a.

  4. یک خطا بسازCreate one failure

    روی Linux daemon را در محیط امن توقف کن؛ یا روی Windows در محیط آموزشی WSL یکپارچه‌سازی توزیع را موقتاً disable کن. نشانه و لایه را قبل از راه‌حل ثبت کن.

    On safe Linux, stop the daemon; or in a learning Windows setup temporarily disable WSL integration for the distro. Record the symptom and suspected layer before fixing it.

  5. راه‌حل و بررسیFix and verify

    همان لایه را اصلاح کن و دقیقاً همان دستور تشخیصی را دوباره اجرا کن تا recovery را ثابت کنی.

    Fix that boundary and rerun the same diagnostic command to prove recovery.

  6. اگر Windows داری، مشترک Engine را ثابت کنOn Windows, prove shared Engine state

    container منحصربه‌فرد بساز و از PowerShell و Ubuntu همان شناسه را ببین.

    Create a uniquely named container and observe the same ID from PowerShell and Ubuntu.

معیار موفقیت · Success criteria

اگر بتوانی بگویی «این دستور فقط کلاینت را ثابت کرد، این یکی سرور را، این خطا در دسترسی بود و این مشترک مورد نشان داد دو ترمینال همان Engine را می‌بینند»، آزمایشگاه موفق است. هدف دستور زیاد نیست؛ هدف مرزبندی درست است.

The lab succeeds when you can say, “this command proved only the Client, this one proved the Server, this error was a permission boundary, and this shared object proved both terminals saw the same Engine.” The goal is not many commands; it is correct boundaries.

در پایان چه چیزهایی را تحویل بدهی؟Lab handoff: an evidence bundle another engineer can review

BoundaryCaptureConclusion you should be able to write
CLIdocker --versionکلاینت فایل اجرایی در این شل قابل‌اجراستthe Client executable is runnable in this shell
Endpoint / Serverdocker version, docker context showکدام context انتخاب شده و آیا سرور پاسخ دادهwhich context is selected and whether Server replied
Enginedocker infoEngine اطلاعات واقعی از نقطهٔ اتصال برگشته‌اندreal Engine facts came back from the endpoint
Runtimedocker run hello-world, docker ps -aساخت/راه‌اندازی/stdout/خروج یک container کوچک کار می‌کندa small container can be created, started, observed, and exited
Windows shared statesame container ID from PowerShell + Ubuntuهر دو کلاینت همان Docker وضعیت را می‌بینندboth clients observe the same Docker state

چند تصویر صفحه به‌تنهایی کافی نیست. بهتر است کنار هر خروجی یک جملهٔ ساده بنویسی: «این دستور چه چیزی را برای من ثابت کرد؟» اگر نتوانی این جمله را بنویسی، احتمالاً هنوز فقط خروجی جمع کرده‌ای و نتیجه نگرفته‌ای.

If you only have screenshots but cannot support one of these conclusions with command/output evidence, the handoff is incomplete. This may feel slower at first, but in real support work it prevents hours of guessing.

مرجع سریعQuick reference and official sources

docker --version
docker version
docker context show
docker context ls
docker info
docker ps
docker run hello-world
systemctl status docker
systemctl start docker
systemctl stop docker

ls -l /var/run/docker.sock
id

wsl --version
wsl -l -v
مدل ماندگار فصلDurable model

یک جمله را از این فصل با خودت نگه دار: «Docker کار نمی‌کند» تشخیص نیست. از نزدیک‌ترین بخش شروع کن و یکی‌یکی جلو برو: CLI، مسیر اتصال، Engine، دسترسی و بعد اجرای واقعی container.

“Docker does not work” is not a diagnosis. Read shell → CLI → context/endpoint → Engine → runtime → kernel one boundary at a time. On Windows, PowerShell and WSL are distinct client paths that can converge on one Docker Desktop Engine.

منابع رسمی بررسی‌شدهOfficial references checked

Install Docker Engine on Ubuntu · Linux post-installation steps · Docker Desktop WSL 2 backend