registry و push
Registries, repositories, tags, and push
image را روی لپتاپ ساختهای و کار میکند. همتیمیات روی سیستم خودش docker run my-app:1.0 میزند، اما چیزی پیدا نمیکند. image هنوز فقط در image store لپتاپ توست؛ وقت آن رسیده آن را در جایی بگذاری که ماشین دیگری هم بتواند دریافتش کند.
You built an image on your laptop and it works. Your teammate runs docker run my-app:1.0 on another machine and gets an error. The image is still only in your laptop’s image store. Now you need somewhere both machines can reach to retrieve it.
ایمیج را ساختهایم؛ پس چرا ماشین همتیمی آن را پیدا نمیکند؟“But didn’t we already build the image?”
برنامه را ساختیم، image هم روی لپتاپ خودمان کاملاً سالم است. حالا همتیمیات روی ماشین خودش همان نام را میزند و Docker میگوید image را پیدا نمیکند. سؤال طبیعی این است: «مگر همین چند دقیقه پیش image را نساختیم؟» بله؛ اما فقط روی ماشین خودمان. هنوز جایی منتشرش نکردهایم که ماشین دیگری بتواند آن را بگیرد.
In Chapter 4 we built the tiny demo-web application. Later chapters ran it, configured it, and checked its health. Now another person uses the same name and Docker says it cannot find the image locally.
$ docker run my-app:1.0 Unable to find image 'my-app:1.0' locally docker: pull access denied for my-app, repository does not exist or may require authorization.
تا اینجا همهچیز محلی بود: build انجام میشد و image در image store همان Docker Engine مینشست. برای اینکه سرور یا همتیمی دقیقاً همان خروجی ساختهشده را اجرا کند، باید آن را به جایی بفرستیم که هر دو طرف به آن دسترسی دارند. اینجا registry وارد داستان میشود؛ نه بهعنوان موتور اجرای تازه، بلکه بهعنوان محل توزیع image.
The first line does not say the app is broken or that no image was ever built. It says this machine has no local image under that name. Docker then tried the default registry, but that reference did not identify an accessible repository. The image exists on your laptop; you have not published it anywhere yet.
این همان فاصلهای است که registry پُر میکند: یک سرویس برای نگهداری و توزیع imageها. قرار نیست با تعریف شروع کنیم؛ اول مسیر حرکت image را ببینیم.
A registry fills that gap: it stores and distributes images. Rather than beginning with a definition, let’s first trace where the image moves.
فلش اول ارسال image از store محلی سازنده به registry است؛ فلش دوم دریافت همان image در store محلی مستقل همتیمی است. Docker دو store محلی را خودکار با هم همگام نمیکند.
The first arrow uploads an image from the developer’s local store to a registry; the second downloads it into the teammate’s separate local store. Docker does not automatically synchronize the two local stores.
اول آدرس را درست بخوان: registry کجاست و repository کدام است؟A registry is not the same thing as a repository
قبل از اولین push، چند اسم شبیه هم داریم که اگر قاطی شوند خطاها گیجکننده میشوند. registry سرویس میزبان imageهاست؛ repository مجموعهٔ نسخههای یک image در همان registry است؛ namespace هم معمولاً مالک یا تیم را مشخص میکند. tag در انتها فقط برچسبی خوانا برای یکی از نسخههاست.
A registry is the service or host that distributes images. Inside it, repositories group images for an application, and each repository can have multiple tags. Docker Hub is one registry, not “the registry.” GHCR, GitLab Container Registry, cloud registries, and private organizational registries are other examples.
| واژهTerm | نقششRole | مثالExample |
|---|---|---|
| registry | میزبان و سرویس دریافت/انتشارThe host/service for image exchange | docker.io، ghcr.io، registry.example.net:5000 |
| namespace / account | مالک یا گروهی که repository زیر آن قرار داردThe user or organization that owns the repository | YOUR_ACCOUNT، team-platform |
| repository | نام مجموعهٔ imageهای یک برنامهThe named collection for an application’s images | codenames-web |
| tag | برچسبی خوانا که به محتوای image اشاره میکندA readable label pointing to image content | 1.0، 1.1.3، latest |
پس در نامی مثل registry.example.net/team/codenames-web:1.0 هر تکه یک سؤال را جواب میدهد: «کجا؟»، «برای چه تیمی؟»، «کدام image؟» و «کدام برچسب؟». وقتی push با خطای دسترسی یا نام اشتباه میشکند، همین چهار بخش اولین چیزهاییاند که باید آرام و جداگانه بررسی کنی.
Build the reference gradually. nginx is a short name; nginx:alpine adds a tag. Your own application needs a namespace: YOUR_ACCOUNT/my-app:1.0. For another registry, include its host too: registry.example.net/team/my-app:1.0.
فلشها فقط بخش هر نام را مشخص میکنند: registry مقصد، namespace مالک، repository برنامه و tag برچسب انتخابی است.
Each arrow identifies one component of the reference: registry destination, namespace owner, repository application, and selected tag.
وقتی registry نوشته نشده، Docker معمولاً Docker Hub را پیشفرض میگیرد. نام بدون namespace مثل nginx به مسیر رسمی پیشفرض Hub میرود؛ اما نامی که تو روی لپتاپ با my-app ساختهای بهخودیخود به حساب تو اشاره نمیکند. برای push و pull برنامهٔ خودت، namespace درست را صریح بنویس.
When no registry host is written, Docker normally defaults to Docker Hub. A short name such as nginx resolves through Hub’s default official-image namespace. A local image you called my-app does not automatically point to your account. For your own image, write the intended namespace explicitly.
حالا که هر تکه را میشناسی، میتوانی قالب کلی را بخوانی: [HOST[:PORT]/]NAMESPACE/REPOSITORY[:TAG]. بخشهای registry میزبان و tag ممکن است حذف شوند و Docker برایشان پیشفرض بگذارد؛ namespace هم در نام کوتاه imageهای رسمی Docker Hub معمولاً library است.
Now that you know each part, read the general pattern: [HOST[:PORT]/]NAMESPACE/REPOSITORY[:TAG]. The registry host and tag may be omitted, in which case Docker applies defaults; short references for Docker Hub official images normally use the library namespace.
Tag تازه، image تازه نمیسازدTagging an image does not copy it
فرض کن image محلیات اسم codenames-web:1.0 دارد، اما registry انتظار دارد namespace هم در نام باشد. لازم نیست دوباره build کنی. با docker tag فقط یک نام تازه به همان image میدهی؛ لایهها کپی نمیشوند و شناسهٔ image عوض نمیشود.
Chapter 4 built the image as demo-web:1.0. First inspect what that name refers to. Then add a publication name that points to the same image.
docker image ls demo-web
docker image inspect demo-web:1.0 --format '{{.Id}}'این تفاوت ساده بعداً خیلی مهم میشود: build محتوا میسازد، tag به همان محتوا نام دیگری میدهد و push آن نام و لایههای لازم را به registry میفرستد. اگر این سه مرحله را از هم جدا ببینی، بخش بزرگی از خطاهای انتشار قابلفهم میشود.
The image ls output lists tags present on this machine. The IMAGE ID identifies local image content; it does not prove the image was published. Replace the placeholder with your actual account namespace:
docker tag demo-web:1.0 YOUR_ACCOUNT/codenames-web:1.0 docker image ls --digests YOUR_ACCOUNT/codenames-web
دو سطر در جدول ممکن است IMAGE ID یکسان داشته باشند. این یعنی دو نام محلی به یک image اشاره میکنند؛ docker tag همهٔ layerها را کپی نکرده و هنوز هیچ بایتی به اینترنت نرفته است. اسم جدید مثل برچسب روی همان جعبه است، نه جعبهٔ دوم.
The two rows may show the same IMAGE ID. That means two local names refer to the same image. docker tag did not copy all the layers or send anything over the network. It is another label on the same box, not a second box.
| کارOperation | چه چیزی عوض میشود؟What changes? | چه چیزی هنوز رخ نداده؟What has not happened yet? |
|---|---|---|
docker build | image تازه بر اساس ورودیهای build میسازدCreates an image from build inputs | بهخودیخود چیزی push نمیشودNothing is pushed by itself |
docker tag | یک نام/tag دیگر به image محلی وصل میکندAdds another local name/tag for the image | محتوا هنوز راهدور نشدهThe content is not remote yet |
docker push | محتوای لازم و manifest را به registry میفرستدSends required content and a manifest to a registry | اجرای برنامه در میزبان دیگر را ثابت نمیکندDoes not prove the app runs elsewhere |
docker pull | image را از registry به store محلی این ماشین میآوردRetrieves the image into this machine’s local store | سلامت برنامه را تضمین نمیکندDoes not guarantee application health |
| پرسشQuestion | image محلیLocal image | image راهدورRemote image |
|---|---|---|
| کجا ثبت شده؟Where is it stored? | image store همان EngineThat Engine’s local image store | repository در registryA repository in a registry |
| آیا ماشین دیگر آن را میبیند؟Can another machine see it? | نه، مگر اینکه جدا منتقل شودNo, unless it is transferred | بله، اگر شبکه و مجوز لازم را داشته باشدYes, with network access and required permission |
| مدرک مفیدUseful evidence | docker image ls و IMAGE ID | push digest، UI registry و pull از مقصدPush digest, registry UI, and a consumer-side pull |
قبل از push باید معلوم باشد چه کسی اجازهٔ نوشتن داردAuthenticate for access, then push
وقتی repository خصوصی است یا میخواهی چیزی منتشر کنی، registry باید هویتت را بشناسد. این مرحله را با خود push قاطی نکن. اگر login شکست میخورد، هنوز اصلاً به مسئلهٔ لایهها و build نرسیدهای. اول دسترسی را درست کن، بعد سراغ انتشار برو.
Before the first push, make sure the repository exists and its visibility (public or private) is what you intend. Some services create repositories automatically and others do not; do not rely on that assumption.
در مثالهای دوره هیچ رمز واقعی را داخل فرمان، Dockerfile یا فایل پروژه نمیگذاریم. اگر registry از token پشتیبانی میکند، از token با کمترین سطح دسترسی لازم استفاده کن و برای ورودی غیرتعاملی سراغ روش امنی مثل --password-stdin برو. هدف این فصل مدیریت سازمانی secret نیست؛ فقط نمیخواهیم برای یک push ساده، اعتبارنامه را بیدلیل در history پخش کنیم.
To push, the registry must know who you are and grant write access to that repository. The current Docker Hub CLI offers a built-in login flow. By default, docker login for Hub uses a device-code/browser flow: enter the one-time code on the official page without putting your account password in a command.
docker login
اگر registry دیگری داری، میزبان آن را به login بده؛ فقط نام میزبان و در صورت نیاز port را بنویس، نه مسیر repository. اگر registry از token پشتیبانی میکند، token محدود به کار لازم و دارای تاریخ انقضا بساز؛ آن را مثل رمز حساب نگه دار.
For another registry, pass its host to login—only the host and optional port, not a repository path. If it supports tokens, create a scoped token with an appropriate expiry and treat it like an account password.
docker login registry.example.net --username YOUR_USER # Enter the token at Docker's password prompt; do not append it to this command.
در اسکریپت یا CI، token را از secret store همان محیط به ورودی استاندارد بده؛ token واقعی را نه در source و نه در فرمانِ ثبتشونده قرار نده:
In a script or CI job, pass the token from that environment’s secret store through standard input. Do not place a real token in source or in a recorded command:
printf '%s' "$REGISTRY_TOKEN" | docker login registry.example.net \ --username "$REGISTRY_USER" --password-stdin
این الگو را فقط وقتی اجرا کن که REGISTRY_TOKEN از secret store تزریق شده و echo/log آن خاموش باشد؛ مقدار واقعی را مستقیم جای آن تایپ نکن. --password-stdin کمک میکند token در history خط فرمان نیاید. اگر اعتبارنامه helper/اعتبارنامه store سیستمعامل در دسترس است از آن استفاده کن؛ در برخی تنظیمها Docker اعتبارنامه را در config.json نگه میدارد و base64 رمزنگاری نیست. دسترسی write به registry حساس است، اما login نه دسترسیهای دیگر را امن میکند و نه خود image را بررسی میکند.
Use this pattern only when REGISTRY_TOKEN is injected by a secret store and shell tracing/logging is disabled; never type the real value directly in place of it. --password-stdin helps keep the token out of shell history. Prefer an operating-system credential helper/store when available; some Docker configurations store credentials in config.json, where base64 is not encryption. Registry write access is sensitive, but login does not secure other access or inspect the image itself.
registry میگوید چه کسی میتواند image را push/pull کند؛ digest میگوید دقیقاً کدام محتوای registry را میگیری؛ اعتماد و امنیت میپرسند سازنده کیست و محتوا چه بررسیای شده. هیچکدام جای دیگری را پر نمیکند.
A registry controls who can push or pull; a digest identifies exact registry content; trust and security ask who produced it and what checks it passed. None replaces the others.
خروجی push را بخوان؛ هر خط میگوید کدام لایه واقعاً منتقل شدRead push as shipping a package
حالا image نام درست دارد و دسترسی هم برقرار است. docker push را اجرا کن و فقط منتظر خط آخر نمان. خروجی لایهبهلایه میگوید چه چیزی در حال ارسال است، چه چیزی قبلاً در registry وجود داشته و در پایان چه digestای برای محتوای منتشرشده ثبت شده است.
Now that the remote name and permission are clear, publish the local image. First verify the destination tag; then read the push output like a shipping receipt.
docker tag demo-web:1.0 YOUR_ACCOUNT/codenames-web:1.0 docker image ls YOUR_ACCOUNT/codenames-web docker push YOUR_ACCOUNT/codenames-web:1.0
پیامهایی مثل Layer already exists خطا نیستند؛ اتفاقاً نشان میدهند registry لایهٔ یکسان را دوباره دریافت نکرده. image از چند لایه تشکیل شده و registry میتواند محتوای مشترک را reuse کند. این رفتار یکی از دلایلی است که push نسخههای نزدیک به هم معمولاً لازم نیست همهٔ بایتها را از صفر بفرستد.
Exact output varies with the Docker version and layer count, but you may see a sequence like this. The short IDs below are illustrative and vary:
The push refers to repository [docker.io/YOUR_ACCOUNT/codenames-web] 2a71: Preparing 7c09: Waiting 2a71: Pushed base-layer: Layer already exists 1.0: digest: sha256:8f...e31 size: 1572
Preparing یعنی Docker این layer را برای ارسال آماده میکند؛ Waiting یعنی نوبتش هنوز نرسیده؛ Pushed یعنی layer لازم منتقل شده؛ Layer already exists یعنی همان محتوای لایه از قبل در مقصد حاضر بوده و دوباره لازم نبوده ارسال شود. در پایان، registry برای tag digest میدهد. push همهٔ حجم image را هر بار دوباره نمیفرستد: layerهای محتوایی مشترک قابلبازاستفادهاند؛ metadata/manifest و tag هم باید در مقصد ثبت شوند.
Preparing means Docker is preparing a layer; Waiting means it has not uploaded yet; Pushed means the required layer was transferred; Layer already exists means the same layer content was already present remotely. At the end, the registry reports a digest for the tag. A push does not resend every byte each time: shared content-addressed layers can be reused, while the destination still records the manifest/metadata and tag.
فلش پیوستهٔ اول بایتهای layer تازه را میفرستد؛ فلش نقطهچین فقط نشان میدهد registry layer یکسان را از قبل دارد؛ فلش سوم manifest و نام tag را ثبت میکند. شکل مفهومی است، نه ترتیب دقیق همزمانی شبکه.
The first solid arrow uploads a new layer; the dashed arrow shows that the registry already has identical layer content; the third records the manifest and tag. This is a conceptual flow, not an exact network scheduling diagram.
خط digest را یادداشت کن؛ بعد در صفحهٔ repository هم ببین tag ظاهر شده باشد. موفقیت push بهتنهایی هنوز ثابت نمیکند همتیمی image را میتواند دریافت و اجرا کند؛ برای آن باید از سمت دریافتکننده آزمایش کنیم.
Record the digest line, then confirm the tag appears in the repository’s tag list. A successful push does not yet prove a teammate can retrieve and run the image; test from the receiving side.
حرف کافی نیست؛ نسخهٔ محلی را بردار و ثابت کن registry واقعاً منبع image شدهProve it: remove the local reference and retrieve it again
تا وقتی image محلی روی ماشینت مانده، اجرای موفق بعد از push چیز مهمی را ثابت نمیکند؛ Docker ممکن است همان نسخهٔ قبلی را استفاده کرده باشد. برای آزمایش واقعی، container مربوط به lab را جمع کن، image محلی را با دقت حذف کن و بعد همان نام کامل را pull کن.
If you only tagged the image and never pushed it, the remote-looking name exists only on your machine and your teammate sees nothing. A stronger proof is to remove the test container, remove every local name pointing to the image, verify they are absent, and then pull.
حالا اگر image دوباره ظاهر شد و container از روی آن اجرا شد، زنجیره کامل شده است: build روی ماشین تو → push به registry → حذف نسخهٔ محلی → pull از registry → run. این آزمایش همان چیزی است که میخواهیم روز استقرار روی سرور به آن اعتماد کنیم.
An image may still be referenced by a container. This lab touches only the exact demo names; do not delete other containers or images. Before docker rm, use docker ps -a --filter name=demo-web and docker inspect demo-web --format '{{.Config.Image}}' to confirm it is the disposable Chapter 4 demo. If the name belongs to another object or its data is uncertain, do not remove it; use an independent lab name and inspect image consumers instead.
# Run this only after confirming demo-web is the disposable Chapter 4 container; otherwise skip. docker rm -f demo-web docker image rm YOUR_ACCOUNT/codenames-web:1.0 demo-web:1.0 docker image ls --digests YOUR_ACCOUNT/codenames-web docker image ls demo-web
اگر docker rm گفت container وجود ندارد، خوب است؛ فرمان بعدی را فقط برای نام دقیق آزمایش اجرا کن. در دو فهرست آخر نباید آن tagها را ببینی. حالا محتوای راهدور را دریافت کن:
If docker rm says the container does not exist, that is fine; continue with the exact lab image names. The final listings should no longer show those tags. Now retrieve the remote content:
docker pull YOUR_ACCOUNT/codenames-web:1.0
docker image ls --digests YOUR_ACCOUNT/codenames-web
docker image inspect YOUR_ACCOUNT/codenames-web:1.0 --format '{{.Id}} {{json .RepoDigests}}'حالا tag دوباره در store محلی حاضر است و RepoDigests باید مرجع registry و digest را نشان دهد. اگر pull از cache layerها را بازاستفاده کرد، باز هم منبع این tag در فرمان registry بوده است؛ نبودن tag پیش از pull و ظاهرشدنش بعد از آن مدرک مهمتری از حجم دانلود است. برای اثبات نهایی، container را اجرا و از میزبان درخواست بفرست.
The tag is now back in the local store, and RepoDigests should show the registry reference and digest. Even if pull reuses cached layers, the source of this reference was the registry. Its absence before the pull and presence afterward matter more than how many bytes were downloaded. For final proof, run it and make a host request.
برای دریافت دقیق همان محتوا، digest کامل واقعی را از خروجی push یا RepoDigests کپی کن و بهجای placeholder بگذار. رشتهٔ نمایشی زیر را عیناً اجرا نکن:
To retrieve exactly that content, copy the complete real digest from the push output or RepoDigests and replace the placeholder below. Do not run the illustrative token literally:
docker pull YOUR_ACCOUNT/codenames-web@sha256:PASTE_REAL_DIGEST_HERE
این شکل repository@digest است، نه repository:tag@digest. tag برای انتخاب انسانخوان است؛ digest محتوای دقیق را مشخص میکند. اگر digest متعلق به index چندسکویی باشد، Docker manifest سازگار با platform خودش را انتخاب میکند.
The form is repository@digest, not repository:tag@digest. The tag is a readable selection; the digest identifies exact content. If it identifies a multi-platform index, Docker selects the manifest for its platform.
docker run -d --name registry-proof -p 8080:3000 YOUR_ACCOUNT/codenames-web:1.0
docker ps --filter name=registry-proof
docker inspect registry-proof --format '{{.Config.Image}} → {{.Image}}'
curl --fail http://localhost:8080در inspect، مقدار اول نامی است که به container دادهای و مقدار دوم شناسهٔ image محلیِ استفادهشده است. پاسخ hello from CodeNames نشان میدهد image دریافتشده فرایند برنامه را اجرا کرده و درخواست از port میزبان به آن رسیده است. این آزمایش ثابت میکند image قابلانتقال است؛ هنوز امنیت، سازگاری معماری دیگر یا کیفیت برنامه را ثابت نمیکند.
In inspect, the first value is the name used to create the container and the second is the local image ID it uses. The hello from CodeNames response proves the retrieved image started the app process and the request reached it through the host port. This demonstrates distribution and execution—not security, compatibility with every architecture, or application quality.
وقتی push یا pull میشکند، اول ببین مشکل نام است، دسترسی است یا اصلاً نسخه منتشر نشدهWhen push or pull fails, isolate the boundary
خطاهای registry خیلی وقتها شبیه هم دیده میشوند، اما از یک جا نمیآیند. قبل از rebuild یا login دوباره، نام کامل image را بخوان: registry، namespace، repository و tag درستاند؟ بعد دسترسی را بررسی کن. در آخر بپرس آیا همان tag واقعاً push شده است یا فقط روی لپتاپ تو وجود دارد.
Registry errors can look alike while coming from different boundaries: destination naming, permission, selected tag, or network connectivity. Before logging in again or rebuilding, ask which boundary lacks evidence.
۱. push میگوید access denied یا repository پیدا نشد1. Push says access denied or repository not found
این ترتیب جلوی عیبیابی تصادفی را میگیرد. اگر tag اشتباه است، login دوباره چیزی را درست نمیکند. اگر دسترسی نداری، build مجدد بیفایده است. و اگر image فقط tag شده ولی push نشده، ماشین دوم هیچ راهی برای دیدنش ندارد.
Observation: Docker cannot write to the destination. Check: inspect docker image ls and confirm the namespace and repository; verify the repository’s Tags page and your write permission. For a private registry, confirm the host in the tag. Repair: retag with the correct full name or obtain write access, then repeat the same push and record its digest.
۲. login موفق است، اما push اجازه نمیدهد2. Login succeeds, but push is denied
مشاهده: authentication انجام شده ولی authorization رد میشود. بررسی: namespace مالک repository و permission token را بررسی کن؛ token صرفاً برای pull نمیتواند push کند. اصلاح: از صاحب repository مجوز لازم یا token با write scope بگیر. اعتبارنامه را در فرمان چاپ نکن؛ بعد push را دوباره بررسی کن. login معتبر به معنی مجوز روی هر repository نیست.
Observation: authentication succeeded, but authorization failed. Check: confirm repository ownership and token permissions; a pull-only token cannot push. Repair: obtain the needed repository access or a write-scoped token. Do not print the credential; retry the push. Being logged in does not grant access to every repository.
۳. image را tag زدی، ولی فراموش کردی push کنی3. You tagged locally but forgot to push
مشاهده: روی لپتاپ نام YOUR_ACCOUNT/codenames-web:1.0 دیده میشود، اما همتیمی آن را pull نمیکند. بررسی: tag در صفحهٔ registry وجود دارد؟ تاریخ push موفق و digest داری؟ محلی image ls فقط store خودت را نشان میدهد. اصلاح: پس از verify کردن destination، push کن؛ سپس از یک ماشین یا store خالی pull را امتحان کن.
Observation: your laptop lists YOUR_ACCOUNT/codenames-web:1.0, but the teammate cannot pull it. Check: does the tag appear remotely, and do you have a successful push digest? Local image ls shows only your store. Repair: verify the destination and push, then test a pull from another machine or empty store.
۴. 1.0 را push کردی، اما 1.1 را pull میکنی4. You pushed 1.0 but are pulling 1.1
مشاهده: registry میگوید tag وجود ندارد. بررسی: namespace/repository/tag را حرفبهحرف با فرمان push و فهرست راهدور مقایسه کن؛ نام بدون tag هم به latest میرود، نه خودکار به 1.0. اصلاح: یا tag موجود 1.0 را pull کن، یا پس از ساخت و بررسی نسخهٔ 1.1 همان tag را push کن. اشتباه را با rebuild بیدلیل پنهان نکن.
Observation: the registry reports a missing tag. Check: compare namespace, repository, and tag character by character with the push command and remote listing. An omitted tag resolves to latest, not automatically to 1.0. Repair: pull the existing 1.0 tag or build and verify 1.1 before pushing that tag.
۵. همتیمی private repository را نمیتواند pull کند5. A teammate cannot pull a private repository
مشاهده: خطای denied/access میگیرد، درحالیکه push تو موفق بوده. بررسی: اعتبارنامه روی ماشین همتیمی، میزبان registry و دسترسی read به همان namespace/repository را جدا بررسی کن. اصلاح: دسترسی pull را به حساب یا token مناسب بده و در همان ماشین login امن انجام بده. image را برای حل مجوز بیدلیل public نکن.
Observation: the teammate gets denied/access errors although your push succeeded. Check: separately verify credentials on their machine, registry host, and read permission for that repository. Repair: grant pull access to the right account/token and authenticate on that machine. Do not make the image public just to bypass an access problem.
۶. token قبلاً کار میکرد؛ حالا منقضی یا لغو شده6. A previously working token expired or was revoked
مشاهده: login یا push رد میشود؛ tag محلی هنوز سر جایش است. بررسی: خطای authentication و وضعیت/انقضای token را در registry بررسی کن؛ از روی image ID نتیجه نگیر اعتبارنامه سالم است. اصلاح: token محدود و تازه را از secret store بگیر، token قبلی را لغو کن و login را تکرار کن؛ سپس push/pull هدفمند را بیازمای.
Observation: authentication or push fails while the local tag remains. Check: read the authentication error and token status/expiry at the registry; an image ID says nothing about credential validity. Repair: issue a scoped replacement through the secret store, revoke the old token, and test the needed push or pull.
۷. tag latest به نسخهای که انتظار داشتی اشاره نمیکند7. latest points somewhere other than you expected
مشاهده: pull بدون tag نسخهٔ موردانتظار را نیاورده. بررسی: tag و digest فعلی را در راهدور و محلی ببین؛ فرمان بدون tag از پیشفرض latest استفاده میکند. اصلاح: release tag صریح مثل :1.1.3 را pull کن و latest را فقط وقتی خودت آگاهانه منتشر کردهای بهکار ببر.
Observation: an untagged pull did not retrieve the version you expected. Check: inspect the current remote and local tag/digest; omitting the tag uses the latest default. Repair: pull an explicit release such as :1.1.3, and use latest only when you intentionally publish it.
۸. همان tag اکنون به محتوای دیگری اشاره میکند8. The same tag now resolves to different content
مشاهده: دو pull از tag ثابت، در زمانهای مختلف image ID/digest متفاوت دارند. بررسی: tag در راهدور mutable است؛ digest قبلی و صفحهٔ تاریخچهٔ publishها را مقایسه کن. اصلاح: برای بازتولید خروجی ساختهشده قبلی digest ثبتشده را pull کن؛ برای release بعدی tag نسخهٔ تازه بساز و تغییر عمدی tagهای آزمایشی را مستند کن.
Observation: pulls of the same tag at different times yield different image IDs or digests. Check: the remote tag is mutable; compare the recorded digest and publication history. Repair: retrieve the earlier artifact by its recorded digest, and publish the next release under a fresh version tag.
۱۸ تمرین؛ هر بار مشخص کن «این image الان کجاست؟»18 exercises: from names to remote evidence
قبل از بازکردن پاسخ، برای هر سناریو یک جمله بنویس: image روی کدام ماشین یا registry وجود دارد، با چه نامی، و هنوز چه چیزی ثابت نشده؟ بعضی سؤالها فقط دربارهٔ نامگذاریاند؛ بعضی از تو میخواهند فرق tag، digest و انتشار واقعی را از روی نشانهها توضیح بدهی.
Before opening each solution, write down a prediction and one piece of evidence. Some prompts ask only for a correct reference; others ask what remains unproven.
تو روی لپتاپت demo-web:1.0 ساختهای. همتیمی روی لپتاپ دیگری همان را اجرا میکند و image محلی ندارد. آیا image تو خودکار به او میرسد؟
You built demo-web:1.0 on your laptop. A teammate runs the same name on another laptop with no local image. Does your image arrive automatically?
اول محل image را پیدا کن · Start with image location
نه. هر Docker Engine image store محلی خودش را دارد. Docker ممکن است registry پیشفرض را امتحان کند، اما build محلی تو به آن store منتقل نشده است.
No. Each Docker Engine has its own local image store. Docker may try the default registry, but your local build was never transferred there.
برای مدرک از ماشین دوم docker image ls demo-web را ببین؛ سپس راهدور reference کامل را pull کن. صرف وجود image در سیستم سازنده، انتشار را ثابت نمیکند.
On the second machine, check docker image ls demo-web, then pull the full remote reference. Seeing the image on its builder does not prove it was published.
تکههای نام registry.example.net:5443/blue-team/api:2.1 را مشخص کن: registry، namespace، repository و tag.
Identify the registry, namespace, repository, and tag in registry.example.net:5443/blue-team/api:2.1.
نام را تکهتکه بخوان · Read the name in parts
registry برابر registry.example.net:5443، namespace برابر blue-team، repository برابر api و tag برابر 2.1 است.
The registry is registry.example.net:5443, namespace blue-team, repository api, and tag 2.1.
port 5443 بخشی از میزبان registry است، نه tag. وجود میزبان صریح میگوید image مقصد Docker Hub پیشفرض نیست.
Port 5443 belongs to the registry host, not the tag. The explicit host means this is not using Docker Hub by default.
Docker Hub username تو nima-dev است. image محلی api:1.0 را به چه نامی tag میزنی تا در repository notes-api push شود؟
Your Docker Hub username is nima-dev. What reference should you tag local api:1.0 with to push it to the notes-api repository?
نامی که registry میفهمد · A registry-qualified name
نام مقصد nima-dev/notes-api:1.0 است؛ فرمان docker tag api:1.0 nima-dev/notes-api:1.0.
Use nima-dev/notes-api:1.0: docker tag api:1.0 nima-dev/notes-api:1.0.
دام این است که نام repository را بدون namespace بنویسی؛ آن نام مسیر حساب خودت را مشخص نمیکند.
The trap is omitting the namespace, which does not identify your account’s repository.
پس از docker tag demo-web:1.0 YOUR_ACCOUNT/codenames-web:1.0، چه چیزی تغییر کرده و چه چیزی هنوز رخ نداده؟
After docker tag demo-web:1.0 YOUR_ACCOUNT/codenames-web:1.0, what changed and what has not happened yet?
tag فقط یک نام تازه میسازد · Tagging is not publishing
یک reference محلی تازه به همان image وصل شده؛ معمولاً هر دو ردیف همان IMAGE ID را دارند. هنوز push انجام نشده و راهدور از این tag خبر ندارد.
A new local reference points to the same image; both rows usually share an IMAGE ID. No push has happened, so the registry does not know about the tag.
docker image ls اثر tag را میسنجد؛ برای اثبات انتشار باید push موفق و سپس pull/راهدور view داشته باشی.
docker image ls shows the tag locally. Publication needs a successful push and then remote/pull evidence.
در push میبینی: یک layer برابر Layer already exists و layer دیگر Pushed. آیا push خراب شده؟
A push reports one layer as Layer already exists and another as Pushed. Did it fail?
این پیام خطا نیست · This is layer reuse
نه؛ این دو پیام عادیاند. registry محتوای layer اول را داشته و دومی تازه فرستاده شده است. خط پایانی tag/digest و exit status فرمان را هم بخوان.
No. Both are normal outcomes. The registry already had the first layer and received the second. Also check the final tag/digest line and command exit status.
Layerهای یکسان قابلاشتراکاند؛ «قبلاً وجود دارد» به معنی موفقیت کل publish نیست تا وقتی فرمان کامل شود و manifest/tag ثبت شود.
Identical layers can be reused. “Already exists” alone does not prove the whole publication succeeded until the command completes and records the manifest/tag.
برای یک گزارش incident که باید دقیقاً همان image آزمایششده را بازسازی کند، فقط :1.2 ثبت میکنی یا digest را هم؟ چرا؟
For an incident report that must reproduce the exact tested image, do you record only :1.2 or also a digest? Why?
برای بازتولید دقیق، digest مهم است · Pin exact content with a digest
digest را هم ثبت کن. tag برای انسان خواناتر است ولی ممکن است بعداً جابهجا شود؛ digest محتوای registry دقیق را pin میکند.
Record the digest too. A tag is easier for people to read but may move later; the digest pins exact registry content.
کنار digest نام برنامه، معماری در صورت اهمیت و زمان آزمایش را یادداشت کن. خود digest ثابت نمیکند image امن یا از سازندهٔ مجاز است.
Record the application name, platform when relevant, and test time alongside it. The digest alone does not prove safety or authorized origin.
همتیمی میگوید docker run my-app:1.0 را اجرا کرده و Docker دنبال image میگردد. تو آن را با همین نام محلی build کردهای. مدرک بعدی چیست؟
A teammate says docker run my-app:1.0 cannot find the image. You built it locally under that name. What is the next evidence to collect?
اسم محلی روی ماشین دیگر وجود ندارد · Local names are local
روی ماشین خودت docker image ls نشان میدهد image محلی حاضر است، اما این به راهدور ارتباطی ندارد. در registry بررسی کن آیا repository/tag درست وجود دارد و آیا push موفق بوده؛ سپس همتیمی باید reference کامل را pull کند.
Your docker image ls proves only that your local copy exists. Check whether the correct remote repository/tag exists and whether push succeeded; then have the teammate pull the full reference.
پیش از rebuild، مرز machine-to-registry را بررسی کن؛ image موجودی معمولاً خطای نام یا انتشار است، نه build.
Before rebuilding, inspect the machine-to-registry boundary. This is usually a naming or publication problem, not a build failure.
آیا Docker Hub همان repository برنامهٔ توست؟ رابطهٔ این دو را در یک جمله توضیح بده.
Is Docker Hub the same thing as your application repository? Explain their relationship in one sentence.
registry ظرف است، repository جای image · Registry vs repository
نه؛ Docker Hub یک registry است و repository تو یکی از مجموعههای image داخل آن است.
No. Docker Hub is a registry; your repository is one named image collection hosted within it.
حساب/namespace مالک repository را مشخص میکند و tag نسخه یا حالت انتخابی را. GHCR و registryهای دیگر هم میتوانند همان repository مفهوم را میزبانی کنند.
The namespace identifies the owner, and a tag identifies a selected version or variant. GHCR and other registries can host the same repository concept.
در README همکارت این فرمان را دیدی: docker login -u alex -p mytoken. چه چیزی خطرناک است و چه جایگزینی پیشنهاد میکنی؟
A teammate’s README contains docker login -u alex -p mytoken. What is risky, and what should replace it?
اعتبارنامه را وارد history نکن · Keep credentials out of history
token در source و احتمالاً shell history/فرایند arguments افشا شده؛ آن را فوراً revoke کن و از logها و نسخههای مخزن هم پاکسازی حسابشده انجام بده. برای Hub از docker login و device flow استفاده کن؛ برای automation token را از secret store با --password-stdin بده.
The token is exposed in source and may be present in shell history/process arguments. Revoke it promptly and carefully address logs and repository history too. Use Docker Hub’s device flow interactively; in automation pass a secret-store token through --password-stdin.
حذف متن از آخرین commit بهتنهایی کافی نیست اگر token قبلاً به راهدور push شده باشد؛ اول revoke، بعد پاکسازی exposure.
Removing the text from the latest commit is not enough if it was pushed remotely. Revoke first, then clean up exposure.
روی ماشین تو docker image ls دو نام نشان میدهد، اما هر دو یک IMAGE ID دارند. آیا دو image کامل مستقل ساختهای؟
Your docker image ls shows two names with the same IMAGE ID. Did you create two independent full images?
یک محتوا میتواند چند نام داشته باشد · Multiple names, same content
احتمالاً نه؛ دو tag به همان image محلی اشاره میکنند. Docker لایههای مشترک را دوبار ذخیره نمیکند.
Probably not. Two tags point to the same local image, and shared layers are not stored twice.
این خروجی با docker tag سازگار است. اما هیچیک از دو ردیف بهتنهایی نمیگوید tag در registry هم وجود دارد.
This is expected after docker tag, but neither row proves that a remote tag exists.
تغییر bug اصلاح با API سازگار است؛ تگ بعدی را مثلاً 1.1.3 میگذاری. آیا باید حالا SemVer را کامل بلد باشی؟
A compatible bug fix is ready and the next tag is, for example, 1.1.3. Must you learn all of SemVer before publishing?
نسخهگذاری را بهاندازهٔ نیاز بفهم · Versioning without detour
نه. برای این فصل کافی است tag روشن، یکتا و مطابق قرارداد تیم باشد. شمارهٔ نسخه کمک میکند releaseها را تشخیص بدهی؛ این تمرین درس کامل SemVer نیست.
No. For this chapter, use a clear, unique tag that follows the team’s convention. Version labels help distinguish releases; this is not a full SemVer lesson.
اگر از نسخهٔ قبلی image جدید ساختی، tag تازهای بگذار و digest را ثبت کن تا مرجع قبلی ناخواسته عوض نشود.
If you built new content, publish it under a new tag and record its digest so the previous reference is not silently changed.
push موفق team/api:1.0 است؛ فرمان pull روی سرور team/api:1.1 میزند و not found میگیرد. محتملترین mismatch چیست؟
Push of team/api:1.0 succeeded; the server pulls team/api:1.1 and gets not found. What is the likely mismatch?
نام و tag را با چیزی که push شده تطبیق بده · Match what was pushed
tagها فرق دارند؛ push کردن 1.0 tag 1.1 را ایجاد نمیکند. فهرست راهدور را ببین و یا 1.0 را pull کن یا بعد از build/آزمون، 1.1 را tag و push کن.
The tags differ. Pushing 1.0 does not create 1.1. Inspect remote tags; either pull 1.0 or build/test, tag, and push 1.1.
تغییر tag فرمان pull راهحل درست است اگر همین نسخه میخواهی؛ rebuild تصادفی فقط زمانی لازم است که محتوا واقعاً باید تازه شود.
Changing the pull tag is correct if 1.0 is the intended release. Rebuilding is needed only when the content should actually change.
تیم میخواهد در release note هم رشتهٔ قابلخواندن داشته باشد و هم بتواند خروجی ساختهشده را دقیقاً pin کند. چه دو مقداری ثبت میکنی؟
The team wants a readable release note and an exact artifact pin. Which two values should it record?
نام خوانا + هویت دقیق · Human label plus exact identity
tag نسخهدار مثل 1.1.3 و digest همان push را هر دو ثبت کن. tag برای گفتوگو و digest برای identity دقیق است.
Record both a version tag such as 1.1.3 and the digest from that push. The tag is readable; the digest gives exact identity.
اگر image چندسکویی است، بدان digest ثبتشده میتواند index کل معماریها باشد؛ آن را با IMAGE ID ماشین محلی اشتباه نگیر.
For a multi-platform image, the digest may identify the multi-platform index. Do not confuse it with a local machine’s IMAGE ID.
دستور docker pull team/api را اجرا میکنی. آیا Docker خودش آخرین نسخهٔ SemVer را انتخاب میکند؟
You run docker pull team/api. Does Docker choose the highest SemVer release automatically?
بدون tag یعنی latest، نه newest SemVer · Omitted tag means latest
نه؛ نبود tag معمولاً به latest پیشفرض میرود. مقایسهٔ نسخههای عددی انجام نمیشود.
No. An omitted tag normally defaults to latest. Docker does not compare version numbers.
برای نسخهٔ معین team/api:1.1.3 یا digest را صریح بده؛ محتوای latest به تصمیم ناشر بستگی دارد.
Specify team/api:1.1.3 or a digest for a particular release. The publisher decides what latest points to.
در پایان push میبینی 1.0: digest: sha256:…. این digest به چه درد میخورد و چه چیزی را تضمین نمیکند؟
A push ends with 1.0: digest: sha256:…. What is the digest useful for, and what does it not guarantee?
digest هویت محتواست، نه مهر اعتماد · Identity, not trust
با آن میتوانی همان محتوای registry را بعداً دقیق pull کنی و در گزارش ثبت کنی. digest ثابت نمیکند ناشر مجاز، image بیخطر یا برنامه درست است.
It lets you retrieve the same registry content later and record it in a report. It does not prove the publisher was authorized, the image is safe, or the app is correct.
برای pull از فرم namespace/repo@sha256:… استفاده میشود. اعتماد ناشر/امضا و اسکن آسیبپذیریها کنترلهای جداگانهاند.
Pull uses the form namespace/repo@sha256:…. Publisher trust/signatures and vulnerability scanning are separate controls.
سرور private image را pull نمیکند. قبل از تعمیر، چهار بررسی متمایز بنویس که نام، authentication، authorization و اتصال را از هم جدا کنند.
A server cannot pull a private image. Before fixing it, list four checks that distinguish naming, authentication, authorization, and connectivity.
چهار مرز را جدا بررسی کن · Separate the four boundaries
نام: registry میزبان/namespace/repo/tag را با release ثبتشده مقایسه کن. Authentication: login یا انقضای اعتبارنامه را از خطای CLI بخوان. Authorization: مطمئن شو token همان repository حق pull دارد. اتصال: DNS/TLS/proxy و دسترسی میزبان به مسیر سرویس registry را بررسی کن.
Naming: compare host, namespace, repository, and tag with the release record. Authentication: inspect login/token-expiry errors. Authorization: verify the token has pull permission for that repository. Connectivity: check DNS/TLS/proxy and access to the registry endpoint.
این تفکیک تعیین میکند اصلاح باید tag، اعتبارنامه، مجوز یا شبکه باشد. همه را با logout/login/build مجدد قاطی نکن.
This separates a tag, credential, permission, or network repair. Do not combine them into random logout/login/rebuild rituals.
روی ماشین A tag demo به digest A میرسد. ناشر همان tag را به digest B تغییر میدهد. ماشین B فردا demo را pull میکند. چه انتظاری داری؟
On machine A, tag demo resolves to digest A. The publisher moves the tag to digest B. What should machine B expect when it pulls demo tomorrow?
tag میتواند جابهجا شود · A tag can move
اگر B tag را از registry resolve/pull کند، محتوای فعلی tag یعنی B را میگیرد؛ A ممکن است هنوز در ماشین A موجود باشد. tag یک شناسهٔ ثابت محتوا نیست.
If B resolves/pulls the tag from the registry, it gets the content currently referenced—B. A may still exist on machine A. The tag is not a fixed content identifier.
برای تکرار دقیق A باید digest ثبتشدهٔ A را pull کنی و دسترسی retention registry به آن manifest را داشته باشی.
To reproduce A exactly, pull its recorded digest and ensure the registry still retains that manifest.
image را push کردهای و میگویی «روی هر ماشین اجرا میشود». چه آزمایش کوتاهی ادعای انتقال را قویتر میکند و چه چیزی هنوز اثباتنشده میماند؟
You pushed an image and claim “it runs on any machine.” What short test strengthens the distribution claim, and what remains unproven?
انتقال را با pull تازه ثابت کن · Prove distribution with a fresh pull
روی ماشین دوم یا پس از حذف tagهای محلی، reference راهدور را pull کن؛ سپس container را با port دلخواه اجرا و HTTP را با curl بررسی کن. docker inspect میتواند image ID استفادهشده را نشان دهد.
On a second machine—or after removing local tags—pull the remote reference, run the container on a chosen host port, and check HTTP with curl. docker inspect can show the image ID in use.
این آزمایش فقط همان محیط و معماری را میآزماید. سازگاری همهٔ معماریها، امنیت، امضای ناشر، پایداری production و کیفیت برنامه هنوز نیاز به آزمون جدا دارند.
This tests only that environment and architecture. All-platform compatibility, security, publisher signatures, production stability, and application quality still require separate checks.
آزمایشگاه: image را از لپتاپت بیرون بفرست و دوباره از صفر برگردانLab: publish, remove, and retrieve the image
یک همتیمی باید برنامه را بدون فایلهای لپتاپ تو اجرا کند
A teammate must run the app without your laptop files
از همان برنامهٔ کوچک قبلی استفاده میکنیم تا موضوع تازه فقط توزیع image باشد. یک نسخهٔ مشخص میسازی، نام registry را به آن میدهی، push میکنی، نسخهٔ محلی را حذف میکنی و بعد دوباره pull و run میکنی. در پایان باید بتوانی با یک درخواست HTTP ثابت کنی image برگشته و واقعاً اجرا شده است.
Reuse Chapter 4’s demo-web folder. The tiny server is enough to observe the publication chain. The goal is to prove the image is transferable, not to build a new app.
۱. وضعیت پایه و tag نسخهدار1. Establish the baseline and a version tag
در نیمهٔ دوم آزمایش یک tag ناموجود را عمداً pull میکنیم. هدف این نیست که خطا بسازیم و رد شویم؛ میخواهیم از متن خطا تشخیص بدهیم «احراز هویت خراب است» با «این tag اصلاً وجود ندارد» چه فرقی دارد.
From the project root, enter demo-web. Confirm the app and previous build; if the Chapter 4 image is absent, build it as version 1.0. Replace the account placeholder in the tag—do not run it literally.
cd demo-web docker image ls demo-web docker build -t demo-web:1.0 . docker tag demo-web:1.0 YOUR_ACCOUNT/codenames-web:1.0 docker image ls --digests YOUR_ACCOUNT/codenames-web
دو tag باید image ID یکسان داشته باشند. این نقطهٔ شروع محلی است؛ هنوز repository راهدور را آماده یا image را ارسال نکردهای.
The two tags should share an image ID. This is the local starting point; the remote repository has not yet received anything.
اگر Docker Hub username نداریIf you do not have a Docker Hub username
یک registry در دسترس که اجازهٔ push داری انتخاب کن و قالب نامش را از مالک سرویس بگیر. در فرمانها فقط بخش YOUR_ACCOUNT/codenames-web را با namespace/repository همان سرویس عوض کن؛ برای registry غیر Hub میزبان را هم اضافه کن.
Choose an available registry where you have push permission and obtain its reference format from the provider. Replace YOUR_ACCOUNT/codenames-web with that namespace/repository; for a non-Hub registry, include its host.
۲. login امن و push2. Authenticate safely and push
برای Docker Hub فرمان docker login را اجرا کن و جریان device-code را در مرورگر کامل کن. برای registry دیگر، login را به میزبان محدود کن و اگر token لازم است آن را در prompt وارد کن. هیچ رمز یا token واقعی را در Dockerfile، فایل مثال، shell دستور قابلثبت یا اسکرینشات نگذار.
For Docker Hub, run docker login and complete the device-code flow in a browser. For another registry, log in to its host and enter a token only at the prompt if required. Never put a real credential in a Dockerfile, example file, recorded shell command, or screenshot.
docker login docker push YOUR_ACCOUNT/codenames-web:1.0
در خروجی پایانیافته tag و digest را ثبت کن. چند خط Layer already exists طبیعی است. وارد registry UI شو و بررسی کن repository و tag واقعاً دیده میشوند؛ این، محلی image ls نیست.
Record the completed tag and digest. Layer already exists is normal. Open the registry UI and confirm the repository and tag are present; that is different evidence from local image ls.
۳. تصویر محلی را حذف کن؛ بعد دوباره دریافتش کن3. Remove the local copy, then retrieve it again
اگر container قدیمی با نام demo-web داری، پیش از حذف image با docker inspect بررسی کن همان تمرین stateless فصل ۴ است؛ فقط همان object را حذف کن. بعد هر دو نام محلی را بردار. اگر Docker گفت image هنوز استفاده میشود، فهرست containerها را بخوان؛ سراغ prune -a نرو.
If an old container named demo-web exists, use docker inspect to confirm it is the stateless Chapter 4 exercise before removing that specific object. Then remove both local names. If Docker says the image is still in use, inspect containers; do not reach for prune -a.
# Run only after confirming demo-web is the disposable Chapter 4 container; otherwise skip.
docker rm -f demo-web
docker image rm YOUR_ACCOUNT/codenames-web:1.0 demo-web:1.0
docker image ls YOUR_ACCOUNT/codenames-web
docker image ls demo-web
docker pull YOUR_ACCOUNT/codenames-web:1.0
docker image ls --digests YOUR_ACCOUNT/codenames-web
docker image inspect YOUR_ACCOUNT/codenames-web:1.0 --format '{{.Id}} {{json .RepoDigests}}'ثبت کن: قبل از pull چه tagهایی نبودند و بعد از pull کدام tag و RepoDigest ظاهر شد. اگر layerها سریع برگشتند یا پیام دانلود کم بود، ممکن است Docker cache مشترک را reuse کرده باشد؛ معیار، نبودن نام قبل و resolve شدن راهدور reference بعد است.
Record which tags were absent before the pull and which tag/RepoDigest appeared afterward. If layers return quickly or little data downloads, Docker may have reused shared cache. The evidence is absence before and successful remote resolution afterward.
حالا tag محلی را بردار تا اجرای بعدی حتماً از reference digest resolve شود. digest کامل را با مقدار واقعی خروجی خودت جایگزین کن:
Now remove the local tag so the next run resolves through the digest reference. Replace the digest with the complete value from your own output:
docker image rm YOUR_ACCOUNT/codenames-web:1.0 docker pull YOUR_ACCOUNT/codenames-web@sha256:PASTE_REAL_DIGEST_HERE docker run -d --name registry-digest-proof -p 8080:3000 \ YOUR_ACCOUNT/codenames-web@sha256:PASTE_REAL_DIGEST_HERE curl --fail http://localhost:8080
اگر pull و run موفق شد، همان خروجی ساختهشده با شناسهٔ محتوایی دقیق دریافت و اجرا شده است. نگهداشتن digest و tag کنار هم مفید است: digest دقت میدهد و tag خوانایی. image محلی alias ممکن است بعد از pull digest به شکل tag ظاهر شود یا نه، پس برای این آزمایش به خروجی خود pull/inspect توجه کن، نه به فرض دربارهٔ نامهای محلی.
If pull and run succeed, the exact content-addressed artifact was retrieved and executed. Keeping both tag and digest is useful: the digest gives precision and the tag gives readability. Local aliases after a digest pull can vary, so read the actual pull/inspect output instead of assuming a particular local name.
۴. container را از image pullشده اجرا کن4. Run a container from the pulled image
docker run -d --name registry-proof -p 8080:3000 YOUR_ACCOUNT/codenames-web:1.0
docker ps --filter name=registry-proof
docker inspect registry-proof --format '{{.Config.Image}} {{.Image}}'
curl --fail http://localhost:8080باید پاسخ hello from CodeNames ببینی. نام image تنظیمشده در container را کنار شناسهٔ image استفادهشده ثبت کن. حالا شاهد داری که tag راهدور دوباره به store محلی آمده، از آن container ساخته شده و مسیر HTTP کار کرده است.
You should see hello from CodeNames. Record the configured image name and the image ID used by the container. This shows that the remote tag returned to the local store, created a container, and served an HTTP request.
۵. نسخهٔ دوم بساز و دو هویت را مقایسه کن5. Publish a second version and compare identities
container را جمع کن. متن پاسخ در server.js را اندکی عوض کن، مثلاً hello from CodeNames v1.1؛ این تغییر باید در source باشد تا build واقعاً محتوای تازه بسازد. نسخهٔ دوم را با tag تازه push کن، نه اینکه 1.0 را بیصدا جایگزین کنی.
Remove the lab container. Change the response text in server.js, for example to hello from CodeNames v1.1. The source change ensures a new build has different content. Push a new tag instead of silently replacing 1.0.
docker rm -f registry-proof registry-digest-proof docker build -t demo-web:1.1 . docker tag demo-web:1.1 YOUR_ACCOUNT/codenames-web:1.1 docker push YOUR_ACCOUNT/codenames-web:1.1 docker image ls --digests YOUR_ACCOUNT/codenames-web
معمولاً digest نسخهٔ 1.1 با digest ثبتشده برای 1.0 فرق میکند چون محتوا عوض شده. برای یک آزمایش جدا و فقط در repository/tag آزمایشی، میتوانی هر دو build را پشت tag متحرک demo push کنی و ببینی همان tag به digest تازه رسیده است؛ این کار را روی release tag یا repository با immutable-tag policy انجام نده. ثبت version tag و digest هر دو، جابهجایی را قابلمشاهده میکند.
The 1.1 digest should normally differ from 1.0 because the content changed. In a separate disposable experiment, you can push both builds under a movable demo tag and observe the tag resolve to a new digest; do not do this with a release tag or a repository enforcing immutable tags. Recording both version tags and digests makes the change visible.
۶. یک خطا تشخیصی بساز و مدرک را بخوان6. Create one diagnostic failure and read the evidence
از tagی استفاده کن که میدانی وجود ندارد. اگر repository عمومی است هم درخواست pull باید نشان دهد tag پیدا نشد؛ اگر private است ممکن است registry برای نام ناموجود و مجوز ناکافی پیام مشابه بدهد، پس علت را فقط از یک متن خطا حدس نزن.
Request a tag you know does not exist. A public repository should report a missing tag; a private registry may give a similar message for a missing name and insufficient access, so do not infer the cause from one error string alone.
docker pull YOUR_ACCOUNT/codenames-web:99.99-not-published docker image ls --digests YOUR_ACCOUNT/codenames-web
خطای موردانتظار، unknown/not found tag است؛ فهرست registry را با tagهای 1.0 و 1.1 مقایسه کن. repair برای اجرای نسخهٔ پایدار، pull کردن tag موجود است؛ در این drill، rebuild راهحل نیست چون مقصد عمداً وجود ندارد.
Expect an unknown/not-found tag. Compare the registry listing with 1.0 and 1.1. To run a known release, pull an existing tag; rebuilding is not the fix because the requested remote reference was intentionally absent.
۷. پیش از پاکسازی، گزارش کوتاه بساز7. Record evidence before cleanup
گزارشت باید نام کامل repository، tagهای منتشرشده، digest هر push، نتیجهٔ pull پس از حذف محلی، پاسخ curl، و علت شکست tag ناموجود را داشته باشد. اعتبارنامهها و token نباید در گزارش باشند.
Your handoff should include the full repository name, published tags, each push digest, pull-after-removal evidence, the curl response, and the diagnosis for the missing tag. Do not include credentials or tokens.
docker rm -f registry-proof registry-digest-proof docker image rm YOUR_ACCOUNT/codenames-web:1.0 YOUR_ACCOUNT/codenames-web:1.1 \ demo-web:1.0 demo-web:1.1
این پاکسازی فقط container و چهار tag همین آزمایش را هدف میگیرد؛ repository راهدور را حذف نمیکند. اگر imageها به container دیگری وصلاند، Docker حذف را رد میکند؛ آن مصرفکننده را شناسایی کن و بدون بررسی دادهاش پاکش نکن. imageهای مشترک base ممکن است بهخاطر مصرف پروژههای دیگر روی ماشین بمانند.
This cleanup targets only the lab container and its four tags; it does not delete the remote repository. If another container uses an image, Docker may refuse removal. Identify that consumer and do not delete it without checking its data. Shared base images may remain because other projects use them.
مرجع سریع؛ هر دستور کدام مرز را طی میکند؟Quick reference: which boundary does each command cross?
docker image lsموجودی store محلی را میبیند؛ نه محتوای registry راLists the local store, not registry contentsdocker tag SRC DSTreference محلی تازه میسازد؛ layerها را کپی یا push نمیکندAdds a local reference; does not copy or push layersdocker login [HOST]برای registry مشخص authentication میکندAuthenticates to a registry hostdocker push NAME:TAGمحتوای لازم و tag را منتشر میکندPublishes required content and a tagdocker pull NAME:TAGtag را به store محلی میآورد؛ latest پیشفرض فقط نامگذاری استRetrieves a tag locally; latest is only the default labeldocker image ls --digestsdigest مرجع راهدور حاضر را نشان میدهدShows available remote digest referencesdocker image inspect NAME --format '{{json .RepoDigests}}'referenceهای repository/digest را میخواندReads repository/digest referencesdocker pull NAME@sha256:…محتوای دقیق digest را میگیرد؛ باید مقدار واقعی را جایگزین کنیRetrieves exact digest content; substitute a real valueمستند رسمی docker image tag قالب مرجع image و پیشفرضها را توضیح میدهد؛ docker login جریان device-code، اعتبارنامه store و --password-stdin را دارد؛ راهنمای Push در Docker Hub و docker image push رفتار ارسال را نشان میدهند. برای digest و pull هم مرجع docker image pull و docker image ls --digests را ببین. رفتار پیشفرض Hub یا امکانات UI ممکن است تغییر کند؛ پیش از آموزش آنها، مستند رسمی را دوباره بررسی کن.
The official docker image tag reference explains image-reference syntax and defaults. docker login documents device-code flow, credential stores, and --password-stdin. The Docker Hub push guide and docker image push explain publication behavior. For digests and retrieval, see docker image pull and docker image ls --digests. Hub defaults and UI features can change; recheck the official docs before teaching them.