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

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.

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

ایمیج را ساخته‌ایم؛ پس چرا ماشین هم‌تیمی آن را پیدا نمی‌کند؟“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 may check locally, then try the default remote
$ 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.

A developer pushes an image from a local store to a registry; a teammate pulls that image into a separate local storeDeveloper laptoplocal image storeRegistryremote image storeTeammate machineseparate local storepush · uploadpull · download

فلش اول ارسال 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 exchangedocker.io، ghcr.io، registry.example.net:5000
namespace / accountمالک یا گروهی که repository زیر آن قرار داردThe user or organization that owns the repositoryYOUR_ACCOUNT، team-platform
repositoryنام مجموعهٔ imageهای یک برنامهThe named collection for an application’s imagescodenames-web
tagبرچسبی خوانا که به محتوای image اشاره می‌کندA readable label pointing to image content1.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.

The image reference registry.example.net/team/codenames-web:1.0 is composed of registry host, namespace, repository and tagregistry.example.net/team/codenames-web:1.0registry hostwhere it livesnamespacewho owns itrepositorywhich applicationtagwhich label

فلش‌ها فقط بخش هر نام را مشخص می‌کنند: 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.

موجودی محلی را بخوانInspect the local inventory
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:

نام مقصد را به همان image وصل کنPoint a destination name at the same image
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 buildimage تازه بر اساس ورودی‌های 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 pullimage را از registry به store محلی این ماشین می‌آوردRetrieves the image into this machine’s local storeسلامت برنامه را تضمین نمی‌کندDoes not guarantee application health
پرسشQuestionimage محلیLocal imageimage راه‌دورRemote image
کجا ثبت شده؟Where is it stored?image store همان EngineThat Engine’s local image storerepository در registryA repository in a registry
آیا ماشین دیگر آن را می‌بیند؟Can another machine see it?نه، مگر اینکه جدا منتقل شودNo, unless it is transferredبله، اگر شبکه و مجوز لازم را داشته باشدYes, with network access and required permission
مدرک مفیدUseful evidencedocker image ls و IMAGE IDpush digest، UI registry و pull از مقصدPush digest, registry UI, and a consumer-side pull

Tag برای آدم‌هاست؛ digest برای اشاره به محتوای دقیقA tag is readable; a digest identifies exact registry content

Tagهایی مثل 1.0 یا 1.1.3 خوانا هستند، اما می‌توانند بعداً به محتوای دیگری اشاره کنند. حتی latest هم جادویی نیست؛ فقط یک tag با همین نام است. Docker خودش تضمین نمی‌کند «latest» حتماً جدیدترین build زمانی باشد.

A tag gives us a readable label such as 1.0 or 1.1.3. But tags are generally mutable: a repository owner can point the same tag at different image content later. Two people pulling codenames-web:demo at different times may therefore get different content.

در مقابل، digest به محتوای مشخص اشاره می‌کند. اگر دقیقاً همان manifest را دوباره بخواهی، digest مرجع محکم‌تری است. قرار نیست از این لحظه همه‌جا digest بنویسی؛ فقط فرق را نگه دار: tag یک نام قابل‌حرکت است، digest هویت یک محتوای مشخص.

latest is also just a tag. If you omit a tag, Docker normally defaults to latest; that is a naming default, not a promise to discover the newest release. A latest tag can be old or absent.

registry برای هر محتوای منتشرشده digest از نوع sha256:… گزارش می‌کند. tag مثل نام متحرک روی قفسه است؛ digest مثل اثرانگشت دقیق همان manifest است. در image چندسکویی، digest ممکن است به manifest index اشاره کند که manifestهای هر معماری را کنار هم معرفی می‌کند؛ با IMAGE ID محلی یکی نیست.

A registry reports a sha256:… digest for published content. A tag is a movable label on a shelf; a digest is the exact content-addressed identity of the registry manifest. For a multi-platform image, the digest may identify an index that points to platform-specific manifests; it is not the same thing as a local IMAGE ID.

نشانهReferenceخواناییReadabilityقابلیت جابه‌جاییCan it move?به‌درد چه می‌خورد؟Useful for
repo:1.1.3بالا؛ انسان نسخه را می‌فهمدHigh; people recognize the labelمعمولاً بله؛ policy registry هم مهم استUsually; registry policy also mattersنسخه‌گذاری روزمره و دستورهای قابل‌خواندنReadable releases and routine commands
repo@sha256:…پایین؛ باید با سند/نسخه همراه شودLow; pair it with release notesبرای همان محتوای digest نهNot for that exact digestبازسازی، pin کردن و ثبت دقیق ورودیReproduction, pinning, and exact provenance
A mutable tag can point to different image digests over time; a recorded digest continues to identify exact contenttag: demomovable labeldigest Asha256:…adigest Bsha256:…bcontent Aexact manifestcontent Bdifferent manifestat time 1 → A; later → B

فلش از tag نشان می‌دهد نام demo در زمان‌های مختلف به digest متفاوت اشاره کرده است. فلش بعدی می‌گوید هر digest محتوای دقیق خودش را مشخص می‌کند؛ digest قبلی با جابه‌جایی tag عوض نمی‌شود.

The tag arrow shows that demo referred to different digests at different times. The next arrows show each digest identifying its own content; moving the tag does not change the earlier digest.

برای بیشتر تمرین‌ها و دستورهای انسانی tag نسخه‌دار کافی است. digest وقتی ارزش پیدا می‌کند که بخواهی دقیقاً همان خروجی ساخته‌شده را دوباره بگیری یا در گزارش بنویسی کدام محتوا آزمایش شده. digest می‌گوید «این همان محتواست»، نه «این محتوا امن یا مورداعتماد است». اعتبار ناشر، اسکن و امضای خروجی ساخته‌شده بحث‌های جدا هستند؛ login یا private بودن هم به‌تنهایی اعتماد را ثابت نمی‌کند.

A version tag is usually enough for everyday learning and readable commands. A digest matters when you need to retrieve exactly the same artifact or record precisely what was tested. A digest says “this is the same content,” not “this content is safe or trusted.” Publisher identity, scanning, and signatures are separate questions; login or repository privacy alone does not establish trust.

در تیم‌ها گاهی tagهایی مثل 1.1.3 را کنار شناسهٔ کوتاه commit مثل git-a1b2c3d هم می‌بینی. commit-tag کمک می‌کند image را به source وصل کنی، ولی اگر سیاست می‌خواهد خروجی ساخته‌شده تغییرناپذیر بماند digest را هم ثبت کن؛ اسم tag به‌تنهایی جلوی جابه‌جایی را نمی‌گیرد. لازم نیست برای این فصل وارد قواعد کامل SemVer شوی.

Teams sometimes publish a tag such as 1.1.3 alongside a commit-oriented tag such as git-a1b2c3d. A commit tag helps connect an image to source, but record the digest when you need exact artifact identity; the tag name alone does not prevent it from moving. This chapter does not require a full SemVer course.

قبل از 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 HubInteractive Docker Hub login
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.

ورود به registry دیگر: token را فقط در prompt وارد کنOther registry: enter the token only at the prompt
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:

الگوی غیرتعاملی؛ متغیر از secret manager تزریق می‌شودNon-interactive pattern; the variable comes from a secret manager
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.

این سه کار را با هم اشتباه نکنDo not confuse these three controls

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.

tag محلی، سپس push همان نام کاملTag locally, then push the full reference
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:

Representative push output · illustrative sampleخروجی نمایشی push
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.

During push, new image layers travel to the registry while identical existing layers are reused; the manifest and tag are publishedLocal imagenew app layershared base layermanifest + tagRegistry repositoryreceive layeralready existsrecord manifest + tagupload bytesreuse · no layer uploadpublish reference

فلش پیوستهٔ اول بایت‌های 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 را بررسی کنCheck image consumers before removal

حالا اگر 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.

حذف محدود و بررسی نبودن دو tag محلیTargeted removal and proof both local tags are absent
# 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:

pull نسخهٔ منتشرشدهPull the published version
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:

pull by exact registry digest
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.

اجرا از tag pullشده و آزمون پاسخRun the pulled tag and test its response
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.

حل‌شدهSolved۰ / ۱۸
تمرین ۱۱٫۱ · Exercise 11.1پیش‌بینی · Prediction۳ min

تو روی لپ‌تاپت 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.

تمرین ۱۱٫۲ · Exercise 11.2نام‌گذاری · Naming۴ min

تکه‌های نام 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.

تمرین ۱۱٫۳ · Exercise 11.3تشخیص · Diagnosis۴ min

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.

تمرین ۱۱٫۴ · Exercise 11.4پیش‌بینی · Prediction۳ min

پس از 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.

تمرین ۱۱٫۵ · Exercise 11.5تفسیر خروجی · Read output۵ min

در 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.

تمرین ۱۱٫۶ · Exercise 11.6انتخاب شناسه · Choose an identifier۴ min

برای یک گزارش 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.

تمرین ۱۱٫۷ · Exercise 11.7عیب‌یابی · Troubleshooting۵ min

هم‌تیمی می‌گوید 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.

تمرین ۱۱٫۸ · Exercise 11.8واژه‌ها · Vocabulary۳ min

آیا 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.

تمرین ۱۱٫۹ · Exercise 11.9امنیت credential · Credential safety۵ min

در 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.

تمرین ۱۱٫۱۰ · Exercise 11.10تفسیر · Interpretation۴ min

روی ماشین تو 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.

تمرین ۱۱٫۱۱ · Exercise 11.11انتخاب نسخه · Choose a version۴ min

تغییر 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.

تمرین ۱۱٫۱۲ · Exercise 11.12عیب‌یابی · Troubleshooting۵ min

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.

تمرین ۱۱٫۱۳ · Exercise 11.13انتخاب شناسه · Choose an identifier۴ min

تیم می‌خواهد در 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.

تمرین ۱۱٫۱۴ · Exercise 11.14تحلیل سیاست · Policy reasoning۴ min

دستور 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.

تمرین ۱۱٫۱۵ · Exercise 11.15تفسیر خروجی · Read output۵ min

در پایان 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.

تمرین ۱۱٫۱۶ · Exercise 11.16گزارش رخداد · Incident report۶ min

سرور 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.

تمرین ۱۱٫۱۷ · Exercise 11.17تحلیل شواهد · Evidence analysis۶ min

روی ماشین 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.

تمرین ۱۱٫۱۸ · Exercise 11.18پیش‌بینی و مدرک · Prediction and evidence۷ min

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

حدود ۴۵ دقیقهAbout 45 minutes

یک هم‌تیمی باید برنامه را بدون فایل‌های لپ‌تاپ تو اجرا کند

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.

baseline and candidate name
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.

publish the named image
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.

نبودن محلی را ثابت کن، بعد از registry بگیرProve local absence, then pull from the registry
# 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:

pull و run با digest واقعیPull and run using the real digest
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

retrieve → run → request
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.

versioned release 1.1
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.

intentional missing-tag drill
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.

cleanup only the lab objects
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 contents
docker tag SRC DSTreference محلی تازه می‌سازد؛ layerها را کپی یا push نمی‌کندAdds a local reference; does not copy or push layers
docker login [HOST]برای registry مشخص authentication می‌کندAuthenticates to a registry host
docker push NAME:TAGمحتوای لازم و tag را منتشر می‌کندPublishes required content and a tag
docker pull NAME:TAGtag را به store محلی می‌آورد؛ latest پیش‌فرض فقط نام‌گذاری استRetrieves a tag locally; latest is only the default label
docker image ls --digestsdigest مرجع راه‌دور حاضر را نشان می‌دهدShows available remote digest references
docker image inspect NAME --format '{{json .RepoDigests}}'referenceهای repository/digest را می‌خواندReads repository/digest references
docker 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.