نصب روی ویندوز، لینوکس و 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.
وقتی 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.
| Piece | What it does | What failure often looks like |
|---|---|---|
| Shell / terminal | برنامهٔ docker را از مسیر پیدا و اجرا میکندfinds and launches the docker executable from PATH | command not found |
| Docker CLI | دستور و flagها را parse میکند و درخواست میسازدparses commands/flags and forms requests | syntax/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 lifecycle | Cannot 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 |
فلشهای رو به پایین مسیر درخواست را نشان میدهند؛ پاسخ در جهت مخالف برمیگردد. 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?
| Command | What it proves | What it does not prove |
|---|---|---|
docker --version | فایل اجرایی محلی Docker CLI پیدا و اجرا میشودthe local Docker CLI executable is found and runs | daemon در دسترس است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 communication | container تو درست تنظیمات شدهyour container is correctly configured |
docker run hello-world | Engine میتواند 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 |
docker --version
docker version
docker context show
docker info --format 'server={{.ServerVersion}} root={{.DockerRootDir}}'
docker ps
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.
sudo systemctl stop docker docker --version docker version docker info docker ps sudo systemctl start docker
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.
خاموشکردن 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.
| Environment | Typical choice | Why |
|---|---|---|
| Linux production/server | Docker Engine | headless، systemd، کنترل مستقیم سیستم میزبانheadless, systemd-managed, direct host control |
| Linux workstation | Engine or Desktop | بسته به نیاز به Desktop ابزارهاdepends on whether Desktop tooling is useful |
| Windows developer | Docker Desktop + WSL2 backend | Linux container بخش پشتی مدیریتشدهmanaged Linux-container backend |
| Windows + Ubuntu WSL | Desktop + WSL integration | امکان استفاده از Linux CLI داخل توزیع و Windows CLI روی همان Desktop بخش پشتیLinux CLI in the distro and Windows CLI can reach the Desktop backend |
Desktop «بهجای Engine» نیست؛ Engine را بهعنوان بخشی از یک محیط توسعهٔ مدیریتشده ارائه میکند.
Desktop is not “instead of Engine”; it provides an Engine as part of a managed development environment.
اگر داخل 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.
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.
sudo apt install \ docker-ce \ docker-ce-cli \ containerd.io \ docker-buildx-plugin \ docker-compose-plugin
| Package | Role in this course | Useful verification |
|---|---|---|
docker-ce | Engine / daemonEngine / daemon | systemctl status docker |
docker-ce-cli | Docker CLI | docker --version |
containerd.io | زمان اجرا manager زیر Engineruntime manager beneath Engine | اطلاعات در docker inforuntime facts in docker info |
docker-buildx-plugin | buildهای مدرن؛ فصل ۴modern builds; Chapter 4 | docker buildx version |
docker-compose-plugin | Compose؛ موضوع فصلهای بعدCompose; covered later | docker compose version |
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.
docker ps sudo docker ps ls -l /var/run/docker.sock id
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 accessDocker 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.
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.
| Thing | What it is | What it is not |
|---|---|---|
| Windows host | سیستمعامل اصلی و محیط Desktop/PowerShellmain OS and Desktop/PowerShell environment | Linux containera Linux container |
| WSL2 | پلتفرم اجرای محیطهای Linux با Linux هستهٔ لینوکسplatform for Linux environments backed by a Linux kernel | خود Docker EngineDocker Engine itself |
| Ubuntu WSL distro | workspace لینوکسی کاربر با سیستمفایل و شل خودشa user Linux workspace with its own filesystem and shell | Docker container یا لزوماً daemon Dockera Docker container or necessarily a Docker daemon |
docker-desktop environment | محیط مدیریتشدهٔ Docker Desktop برای بخش پشتی خودشDocker Desktop’s managed backend environment | Ubuntu روزمرهٔ توyour everyday Ubuntu distro |
| Docker container | processهای ایزولهشدهای که 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.”
فلشها درخواست مسیر را نشان میدهند. دو کلاینت مسیر در بخش پشتی/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.
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.
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}}'
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:
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.
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.
راهاندازی دوباره کردن همهچیز ممکن است نشانه را موقتاً پاک کند، ولی مدل ذهنی نمیسازد. دستور تشخیصی باید همان فرضیهای را که داری امتحان کند.
Restarting everything may temporarily remove a symptom, but it teaches little. A diagnostic command should test the specific hypothesis you have.
| Symptom | Likely boundary | Evidence → fix → verify |
|---|---|---|
docker: command not found | shell / PATH / CLI | command -v docker → install/fix PATH → docker --version |
Cannot connect to the Docker daemon | context / endpoint / daemon | docker context show + service/Desktop status → fix target/daemon → docker info |
permission denied ... docker.sock | local socket permission | sudo docker ps + ls -l /var/run/docker.sock → deliberate access fix → normal docker ps |
| PowerShell works, Ubuntu says command not found | WSL distro client path | command -v docker + WSL Integration → enable/fix distro path → docker info in Ubuntu |
| PowerShell works, Ubuntu cannot reach daemon | WSL integration / context / backend | wsl -l -v + Desktop WSL Integration + docker context show → fix integration → shared-state test |
| “my images disappeared” | wrong Engine/context/store | docker 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.
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:
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.
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.
«آیا همان کلاینت به همان 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.
wsl -l -v
docker context show
docker version
docker info --format 'server={{.ServerVersion}}'
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.
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.
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.
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.
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.
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.
در 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.
چرا 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.
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.
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.
چرا اضافهکردن کاربر به 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.
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.
یک تفاوت بنیادی بین 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.
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.
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.
اگر 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.
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.
بعد از 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.
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.
یک 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.
در 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.
یک گزارش کوتاه بنویس که ثابت کند 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
فرض کن یک لپتاپ تازه دستت رسیده و باید به نفر بعدی تحویلش بدهی. نوشتن «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.
- محیط را شناسایی کنIdentify the environment
Linux یا Windows+WSL2؟ اگر Windows است،
wsl --versionوwsl -l -vرا ثبت کن.Linux or Windows+WSL2? On Windows, record
wsl --versionandwsl -l -v. - کلاینت و سرور را جدا ثابت کنProve client and server separately
docker --version،docker version،docker context showوdocker infoرا با یک جملهٔ تفسیر برای هرکدام ذخیره کن.Capture
docker --version,docker version,docker context show, anddocker info, with one sentence interpreting each. - یک برنامه واقعی کوچک اجرا کنRun one real small workload
docker run hello-worldو بعدdocker ps -aرا بخوان.Run
docker run hello-worldand then inspectdocker ps -a. - یک خطا بساز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.
- راهحل و بررسیFix and verify
همان لایه را اصلاح کن و دقیقاً همان دستور تشخیصی را دوباره اجرا کن تا recovery را ثابت کنی.
Fix that boundary and rerun the same diagnostic command to prove recovery.
- اگر 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
| Boundary | Capture | Conclusion you should be able to write |
|---|---|---|
| CLI | docker --version | کلاینت فایل اجرایی در این شل قابلاجراستthe Client executable is runnable in this shell |
| Endpoint / Server | docker version, docker context show | کدام context انتخاب شده و آیا سرور پاسخ دادهwhich context is selected and whether Server replied |
| Engine | docker info | Engine اطلاعات واقعی از نقطهٔ اتصال برگشتهاندreal Engine facts came back from the endpoint |
| Runtime | docker run hello-world, docker ps -a | ساخت/راهاندازی/stdout/خروج یک container کوچک کار میکندa small container can be created, started, observed, and exited |
| Windows shared state | same 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
یک جمله را از این فصل با خودت نگه دار: «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.
Install Docker Engine on Ubuntu · Linux post-installation steps · Docker Desktop WSL 2 backend