---
title: 'Etiketleme Düzeni'
source: 'https://academia.sh/tr/kurslar/konteynerler/etiketleme-duzeni'
course: Konteynerler
language: tr
updated: '2026-08-17T18:09:05+00:00'
license: 'CC BY-SA 4.0'
---

# Etiketleme Düzeni

Katmanlı bir imaj deposunda etiket ölçülür: yirmi derlemenin kaç ayrı içerik özeti ürettiği ve aynı özete kaç etiketin işaret ettiği sayılır, etiket taşındığında dört katmanın gerçekten kaçının değiştiği hesaplanır ve bir dağıtımın kaynağına özetten geriye izlenebilme oranı üç ayrı kayıt disiplini altında ölçülür.

Önceki ders üç temel adayını sabit içerikmiş gibi ele aldı. Oysa hiçbir temel içerikle seçilmez:
bir **adla** çekilir. Aynı şey üretilen imaj için de geçerlidir — bir derleme yeni bir içerik
üretir, ama dağıtım kaydında duran şey addır.

M22/K01'in yapı çıktısı depolarında **taşınabilir etiket** ile **değişmez sürüm** ayrımı
ölçülmüştü; o sayım burada tekrarlanmaz. Buradaki soru bir katman aşağıdadır: imaj tek bir nesne
değil, bir katman listesidir. Etiket bu listenin tamamına mı işaret eder, aynı listeye kaç ad
birden işaret edebilir ve bir ad taşındığında listenin kaçıncı satırı gerçekten değişir?

**IM31.** Depo modeli iki defter tutar: imaj özeti → manifest ve etiket → imaj özeti. Erişim
denetimi ve ağ katmanı modelin dışındadır. **IM32.** Derleme geçmişi kendi üretecimizden gelir;
tohum `20260604` görünürdür, 20 derleme yapılır ve derlemelerin dörtte biri aynı kaynak sürümünden
yeniden derlemedir. **IM33.** İmaj dört katmandır — önceki dersin küçültülmüş temeli üzerine
bağımlılıklar, uygulama ve yapılandırma — ve toplamı 34,5 MB'dir.

## Etiket Neye İşaret Eder

Etiket doğrudan bayta işaret etmez. Zincir üç düzeylidir: etiket bir **imaj özetini** gösterir,
imaj özeti bir **manifesti** adresler, manifest de katman özetlerini sırayla listeler. Aynı adın
aynı katman kümesini getirmesini sağlayan şey bu üç düzeydir.

**IM34.** Etiket düzeni şudur: her derlemeye bir değişmez sürüm etiketi (`s-1`, `s-2`, …) verilir;
`son` her derlemede taşınır, `kararli` yalnız gecelik toplu işi temiz koşan derlemelere taşınır,
`dal-hazirlik` her dördüncü derlemede taşınır. **IM35.** Derlemelerin dörtte üçü yapılandırma
nesnesine kaynak sürümü alanını yazar; boru hattı dışında elle yapılanlar yazmaz.

```js
// olcum-agi/imaj.mjs — katmanli imaj deposunda derleme gecmisi ve etiketler (model)
import { createHash } from "node:crypto";

export const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
export const ozet = (s) => createHash("sha256").update(s).digest("hex").slice(0, 12);

// [ad, bayt, kaynaktan bagimsiz degisme olasiligi]. Uygulama katmani kaynaga baglidir.
export const KATMAN = [["temel", 10.5e6, 0.08], ["bagimliliklar", 16.0e6, 0.25],
  ["uygulama", 7.2e6, null], ["yapilandirma", 0.8e6, 0.30]];

export const gecmis = (n = 20, tohum = 20260604) => {
  const r = uretec(tohum);
  const surum = [1, 1, 1, 1];
  const liste = [];
  let kaynak = 1, gun = 0;
  for (let no = 1; no <= n; no++) {
    gun += 1 + Math.round(r() * 8);
    const yeniKaynak = r() > 0.25;      // dortte biri ayni kaynaktan yeniden derlemedir
    if (yeniKaynak) { kaynak += 1; surum[2] += 1; }
    KATMAN.forEach(([, , p], k) => { if (p !== null && r() < p) surum[k] += 1; });
    const katmanlar = KATMAN.map(([ad, bayt], k) => ({ ad, bayt, ozet: ozet(`${ad}@${surum[k]}`) }));
    liste.push({
      no, gun, kaynak: `k-${String(kaynak).padStart(3, "0")}`, katmanlar,
      imaj: ozet("manifest:" + katmanlar.map((k) => k.ozet).join("|")),
      kaynakYazildi: r() > 0.25,        // boru hatti disinda elle derlemeler alani yazmaz
      temizKostu: r() > 0.40,           // gecelik toplu is temiz kostu mu
    });
  }
  return liste;
};

// Etiket defteri: her derlemeye degismez surum etiketi, tasinabilir etiketler kosula bagli.
export const etiketle = (G) => {
  const defter = new Map();             // etiket -> imaj ozeti
  for (const d of G) {
    defter.set(`s-${d.no}`, d.imaj);
    defter.set("son", d.imaj);
    if (d.temizKostu) defter.set("kararli", d.imaj);
    if (d.no % 4 === 0) defter.set("dal-hazirlik", d.imaj);
  }
  return defter;
};

if (import.meta.url === `file://${process.argv[1]}`) {
  const G = gecmis();
  const gorulen = new Set();
  console.log("no".padEnd(4) + "gun".padEnd(5) + "kaynak".padEnd(8) + "imaj ozeti".padEnd(15) + "durum");
  for (const d of G) {
    const tekrar = gorulen.has(d.imaj);
    gorulen.add(d.imaj);
    console.log(String(d.no).padEnd(4) + String(d.gun).padEnd(5) + d.kaynak.padEnd(8) +
      d.imaj.padEnd(15) + (tekrar ? "tekrar" : "yeni"));
  }
  const defter = etiketle(G);
  const fanIn = new Map();
  for (const [etiket, imaj] of defter) fanIn.set(imaj, [...(fanIn.get(imaj) ?? []), etiket]);
  const cok = [...fanIn.entries()].sort((a, b) => b[1].length - a[1].length);
  console.log(`\n${G.length} derleme ${gorulen.size} ayri imaj ozeti uretti; ` +
    `${G.length - gorulen.size} derleme onceki bir ozeti yeniden uretti`);
  console.log(`${defter.size} etiket ${fanIn.size} ayri ozete isaret ediyor`);
  for (const [imaj, etiketler] of cok.slice(0, 3)) {
    console.log(`  ${imaj}: ${etiketler.length} etiket -> ${etiketler.join(", ")}`);
  }
  console.log(`kaynak alani yazilmis derleme: ${G.filter((d) => d.kaynakYazildi).length}/${G.length}`);
}
```

```
no  gun  kaynak  imaj ozeti     durum
1   7    k-002   1c8cb1388bf2   yeni
2   11   k-002   908c2c77fc0d   yeni
3   18   k-002   908c2c77fc0d   tekrar
4   25   k-003   d332a3b518f8   yeni
5   29   k-004   3d130b865763   yeni
6   33   k-005   9331a50e2dfd   yeni
7   41   k-006   286596c96b64   yeni
8   45   k-007   847e6e31dbfc   yeni
9   54   k-008   0542d8380547   yeni
10  60   k-009   17d20393c63f   yeni
11  66   k-010   86378989704b   yeni
12  73   k-010   86378989704b   tekrar
13  78   k-010   2f1382fedd1e   yeni
14  83   k-011   3d4cfae4fefc   yeni
15  88   k-011   774b1e11c564   yeni
16  91   k-012   8b84de0171eb   yeni
17  95   k-013   77d3df14dcdb   yeni
18  101  k-014   77112bd049c4   yeni
19  105  k-015   65de4c0ce42a   yeni
20  111  k-015   65de4c0ce42a   tekrar

20 derleme 17 ayri imaj ozeti uretti; 3 derleme onceki bir ozeti yeniden uretti
23 etiket 17 ayri ozete isaret ediyor
  65de4c0ce42a: 5 etiket -> son, kararli, dal-hazirlik, s-19, s-20
  908c2c77fc0d: 2 etiket -> s-2, s-3
  86378989704b: 2 etiket -> s-11, s-12
kaynak alani yazilmis derleme: 14/20
```

Yirmi derleme **on yedi** ayrı imaj özeti üretmiştir. Üç derleme, önceki bir derlemenin özetini
yeniden üretmiştir: kaynak da katmanlar da değişmediği için manifest aynı çıkmıştır. Bu, önceki
dersin belirlenimci derleme disiplininin görünür kanıtıdır — damga koyan bir derlemede yirmi
derleme yirmi ayrı özet verirdi.

İkinci sayı ters yöndedir: **23 etiket 17 özete işaret eder.** Bir özetin beş adı vardır —
`son`, `kararli`, `dal-hazirlik`, `s-19`, `s-20`. İkisi değişmezdir, üçü bir sonraki derlemede
başka bir özeti gösterecektir. Aynı nesneye beş addan bakılabilmesi bir kusur değil, deponun
düzenidir; kusur, dağıtım kaydına bu adlardan hangisinin yazıldığının nesneyi belirleyip
belirlemediğidir.

## Etiket Taşındığında Ne Değişir

Etiket taşındığında yeni bir imaj adreslenir, ama imajın tamamı yeni değildir. Manifest bir
katman listesidir ve iki manifest listenin bazı satırlarını paylaşabilir.

```js
// olcum-agi/tasima.mjs — etiket tasindiginda kac katman gercekten degisti (model)
import { gecmis, KATMAN } from "./imaj.mjs";

const G = gecmis();
const TAM = KATMAN.reduce((t, [, b]) => t + b, 0);
const mb = (b) => (b / 1e6).toFixed(1) + " MB";

// Etiketin hedef aldigi derlemeler, sirayla.
const hedefler = {
  son: G,
  kararli: G.filter((d) => d.temizKostu),
  "dal-hazirlik": G.filter((d) => d.no % 4 === 0),
};

console.log("etiket".padEnd(15) + "tasima".padEnd(8) + "0 katman".padEnd(10) +
  "1 katman".padEnd(10) + "2+ katman".padEnd(11) + "yeni bayt".padEnd(11) + "tam bayt");
const ayrinti = [];
for (const [etiket, dizi] of Object.entries(hedefler)) {
  const dagilim = [0, 0, 0];
  let yeniToplam = 0;
  for (let i = 1; i < dizi.length; i++) {
    const eski = dizi[i - 1].katmanlar, yeni = dizi[i].katmanlar;
    const degisen = yeni.filter((k, j) => k.ozet !== eski[j].ozet);
    const bayt = degisen.reduce((t, k) => t + k.bayt, 0);
    yeniToplam += bayt;
    dagilim[Math.min(degisen.length, 2)] += 1;
    if (etiket === "kararli" && degisen.length !== 1) {   // 1 katman olagan hal; ozette var
      ayrinti.push(`s-${dizi[i - 1].no} -> s-${dizi[i].no}`.padEnd(16) +
        `${degisen.length}/4`.padEnd(8) +
        (degisen.map((k) => k.ad).join(", ") || "-").padEnd(39) + mb(bayt));
    }
  }
  const tasima = dizi.length - 1;
  console.log(etiket.padEnd(15) + String(tasima).padEnd(8) + String(dagilim[0]).padEnd(10) +
    String(dagilim[1]).padEnd(10) + String(dagilim[2]).padEnd(11) +
    mb(yeniToplam).padEnd(11) + mb(tasima * TAM));
}

console.log('\n"kararli" tasimalarinda bir katmandan baska sayida degisenler:');
console.log("tasima".padEnd(16) + "katman".padEnd(8) + "degisen".padEnd(39) + "yeni bayt");
for (const s of ayrinti) console.log(s);

// Katman basina: 19 "son" tasimasinin kacinda degisti?
const say = {};
for (let i = 1; i < G.length; i++)
  G[i].katmanlar.forEach((k, j) => {
    if (k.ozet !== G[i - 1].katmanlar[j].ozet) say[k.ad] = (say[k.ad] ?? 0) + 1;
  });
console.log("\nkatman basina degisim (19 tasimada): " +
  KATMAN.map(([ad]) => `${ad} ${say[ad] ?? 0}`).join(", "));
console.log(`tam imaj ${mb(TAM)}; degismez surum etiketi ${G.length}, tasinabilir etiket ` +
  `${Object.keys(hedefler).length}`);
```

```
etiket         tasima  0 katman  1 katman  2+ katman  yeni bayt  tam bayt
son            19      3         10        6          141.7 MB   655.5 MB
kararli        14      1         8         5          120.1 MB   483.0 MB
dal-hazirlik   4       0         0         4          58.5 MB    138.0 MB

"kararli" tasimalarinda bir katmandan baska sayida degisenler:
tasima          katman  degisen                                yeni bayt
s-2 -> s-3      0/4     -                                      0.0 MB
s-3 -> s-5      3/4     temel, uygulama, yapilandirma          18.5 MB
s-6 -> s-8      2/4     uygulama, yapilandirma                 8.0 MB
s-8 -> s-10     3/4     bagimliliklar, uygulama, yapilandirma  24.0 MB
s-16 -> s-17    2/4     uygulama, yapilandirma                 8.0 MB
s-18 -> s-20    2/4     uygulama, yapilandirma                 8.0 MB

katman basina degisim (19 tasimada): temel 1, bagimliliklar 2, uygulama 13, yapilandirma 7
tam imaj 34.5 MB; degismez surum etiketi 20, tasinabilir etiket 3
```

`son` etiketi on dokuz kez taşınmıştır. Bu on dokuz taşımanın **onunda yalnız bir katman**, üçünde
**hiçbir katman** değişmiştir. Sıfır katmanlı taşıma etiketin taşındığı ama içeriğin aynı kaldığı
durumdur: ad yeni bir özeti gösterir, özet aynı manifesti adresler, indirilecek bayt yoktur.
Dışarıdan bakan tarafta ise "yeni bir imaj yayımlandı" görünür ve bir dağıtım tetiklenebilir.

Bayt sütunları taşımanın gerçek ağırlığını verir: on dokuz taşımada değişen toplam **141,7 MB**,
aynı on dokuz imajın toplam boyutu ise **655,5 MB**. Katman paylaşımı taşımaların yükünün yüzde
78'ini ortadan kaldırmıştır. `dal-hazirlik` etiketi tersi uçtadır — dört taşımasının dördünde de
iki ya da daha çok katman değişmiştir, çünkü arasında dört derleme birikmiştir. **Etiketin
taşınma sıklığı azaldıkça taşıma başına değişen katman sayısı artar.**

Son satır değişimin nereden geldiğini gösterir: on dokuz taşımada uygulama katmanı 13, yapılandırma
7, bağımlılıklar 2, **temel yalnız 1 kez** değişmiştir. Bu, önceki dersin güncelleme ölçümüyle aynı
yöne bakar — alt katmanlar seyrek değişir, üst katmanlar neredeyse her derlemede.

## Özetten Kaynağa Geri Dönüş

Şimdiye kadar ölçülen her şey ileri yöndeydi: kaynaktan derlemeye, derlemeden özete, özetten
etikete. Olay sırasında sorulan soru ters yöndedir — üretimde koşan bu nesne hangi kaynaktan
geldi?

**IM36.** Yirmi dört dağıtım kurgudur; tohum `20260707` görünürdür ve istenen adın türü —
taşınabilir etiket, değişmez sürüm etiketi ya da doğrudan özet — üreteçten gelir. Zincir iki
halkadan oluşur: dağıtım kaydından imaj özetine, imaj özetinden kaynak sürümüne.

```js
// olcum-agi/izlenebilirlik.mjs — bir dagitimin kaynagi ozetten geriye izlenebiliyor mu (model)
import { gecmis, uretec } from "./imaj.mjs";

const G = gecmis();
const r = uretec(20260707);
const ALAN_BAYT = 96;        // kaynak surumu + kosum kimligi + zaman damgasi (kurgu)
const TAM = 34.5e6;

// 24 dagitim: gun ve istenen ad. Ad ya tasinabilir etiket, ya surum etiketi, ya dogrudan ozettir.
const dagitimlar = [];
let gun = 3;
while (dagitimlar.length < 24) {
  gun += 1 + Math.round(r() * 7);
  const p = r();
  dagitimlar.push({ gun, tur: p < 0.60 ? "tasinabilir" : p < 0.85 ? "surum" : "ozet" });
}

// Etiket defteri gune gore ilerletilir: dagitim aninda cozulen sey o anki hedeftir.
const defter = new Map();
let sirada = 0;
for (const d of dagitimlar) {
  while (sirada < G.length && G[sirada].gun <= d.gun) {
    const b = G[sirada++];
    defter.set("son", b); defter.set(`s-${b.no}`, b);
    if (b.temizKostu) defter.set("kararli", b);
  }
  const surumEtiketleri = [...defter.keys()].filter((k) => k.startsWith("s-"));
  d.ad = d.tur === "tasinabilir" ? (r() < 0.6 ? "kararli" : "son")
    : d.tur === "surum" ? surumEtiketleri[surumEtiketleri.length - 1]
    : "ozet:dogrudan";
  d.hedef = d.tur === "ozet" ? defter.get("son") : defter.get(d.ad);
}

// Degismez surum etiketi, defter onu tasimayi reddettigi surece ozeti belirler; tasinabilir
// etiket belirlemez. Uc disiplin: (1) kayit yalniz istenen adi yazar, (2) cozulen ozeti de
// yazar, (3) ayrica her derleme kaynak alanini yazar.
const ozetiBelli = (d) => d.tur === "ozet" || d.tur === "surum";
const izlenebilir = (hepsindeOzet, hepsindeKaynak) =>
  dagitimlar.filter((d) => (hepsindeOzet || ozetiBelli(d)) &&
    (hepsindeKaynak || d.hedef.kaynakYazildi)).length;

const N = dagitimlar.length;
console.log("disiplin".padEnd(34) + "ozet biliniyor".padEnd(16) + "kaynak okunuyor");
console.log("kayitta yalniz istenen ad".padEnd(34) +
  `${dagitimlar.filter(ozetiBelli).length}/${N}`.padEnd(16) +
  `${izlenebilir(false, false)}/${N}`);
console.log("kayitta cozulen ozet de var".padEnd(34) + `${N}/${N}`.padEnd(16) +
  `${izlenebilir(true, false)}/${N}`);
console.log("ustune her derleme kaynagi yazar".padEnd(34) + `${N}/${N}`.padEnd(16) +
  `${izlenebilir(true, true)}/${N}`);

// Ters yon: ayni kaynak surumu kac ayri imaj ozeti uretti?
const kaynaktan = new Map();
for (const b of G) kaynaktan.set(b.kaynak, new Set([...(kaynaktan.get(b.kaynak) ?? []), b.imaj]));
const cokluk = [...kaynaktan.entries()].filter(([, s]) => s.size > 1);
console.log(`\ndagitim turu: tasinabilir ${dagitimlar.filter((d) => d.tur === "tasinabilir").length}, ` +
  `surum etiketi ${dagitimlar.filter((d) => d.tur === "surum").length}, ` +
  `dogrudan ozet ${dagitimlar.filter((d) => d.tur === "ozet").length}`);
console.log(`${kaynaktan.size} kaynak surumunun ${cokluk.length} tanesi birden cok imaj ozeti uretti: ` +
  cokluk.map(([k, s]) => `${k} -> ${s.size}`).join(", "));
console.log(`izlenebilirligin bedeli: imaj basina ${ALAN_BAYT} bayt, tam imajin ` +
  `${Math.round(TAM / ALAN_BAYT)}'te 1'i; dagitim kaydina ${N} x 1 alan`);
```

```
disiplin                          ozet biliniyor  kaynak okunuyor
kayitta yalniz istenen ad         14/24           9/24
kayitta cozulen ozet de var       24/24           17/24
ustune her derleme kaynagi yazar  24/24           24/24

dagitim turu: tasinabilir 10, surum etiketi 10, dogrudan ozet 4
14 kaynak surumunun 3 tanesi birden cok imaj ozeti uretti: k-002 -> 2, k-010 -> 2, k-011 -> 2
izlenebilirligin bedeli: imaj basina 96 bayt, tam imajin 359375'te 1'i; dagitim kaydina 24 x 1 alan
```

Üç satır bir merdivendir. Mevcut düzende yirmi dört dağıtımın **dokuzunun** kaynağı okunabilir.
Kayıp iki yerdedir: on dağıtım taşınabilir bir adla yapıldığı için hangi özeti aldığı kayıtta
yoktur, ve özeti bilinen dağıtımların bir bölümünde de hedef derleme kaynak alanını yazmamıştır.
Kayda çözülen özetin de yazılması oranı **17/24**'e çıkarır; kaynak alanının her derlemede
yazılması **24/24** yapar.

Değişmez sürüm etiketiyle yapılan on dağıtımın özeti belirlemesi bir varsayıma dayanır: defterin
`s-N` etiketini taşımayı reddetmesi. Bu reddetme bir özellik değil, deponun uyguladığı bir
kuraldır — M22/K01'de ölçülen değişmezlik denetiminin buradaki karşılığıdır. Kural uygulanmazsa
ilk satırdaki 14 de düşer ve merdivenin ilk basamağı dörde iner.

İkinci sonuç ters yöndedir. On dört kaynak sürümünün **üçü** birden çok imaj özeti üretmiştir:
kaynak değişmeden bağımlılık ya da yapılandırma katmanı değişmiştir. Geriye izlenebilirlik
kaynağa kadar götürür, kaynaktan ileriye tek bir nesneye götürmez.

**Bu yalıtımın bedeli sayıyla küçüktür.** Kaynak alanı imaj başına 96 bayttır — tam imajın 359
binde biri — ve dağıtım kaydına eklenen tek bir alandır. Ölçülen kazanç, 9/24'ten 24/24'e çıkan
bir orandır. **Yalıtımın delindiği yer** ise etiket defterinin kendisidir: defter imajın içinde
değil, deponun içindedir. İmaj taşınabilir bir çıktıdır, adı taşınabilir değildir; başka bir
depoya kopyalanan imaj etiketlerini yanında götürmez, yalnız özetini götürür.

## Özet

- Etiket üç düzeyli bir zincirdir: etiket bir imaj özetini, imaj özeti bir manifesti, manifest de
  katman özetlerini gösterir. Etiket bayta değil, listeye işaret eder.
- 20 derleme 17 ayrı imaj özeti üretmiştir; 3 derleme önceki bir özeti yeniden üretmiştir. Bu,
  belirlenimci derlemenin görünür kanıtıdır — damgalı derlemede sayı 20 olurdu.
- 23 etiket 17 özete işaret eder; bir özetin beş adı vardır. Kusur çok adlılık değil, kayda
  yazılan adın nesneyi belirleyip belirlememesidir.
- `son` etiketinin 19 taşımasının 10'unda tek katman, 3'ünde hiçbir katman değişmiştir. Değişen
  toplam 141,7 MB, aynı imajların toplamı 655,5 MB'dir: paylaşım yükün yüzde 78'ini kaldırır.
  Etiketin taşınma sıklığı azaldıkça taşıma başına değişen katman sayısı artar.
- Dağıtımın kaynağına geri izlenebilme oranı kayıt disiplinine bağlıdır: 9/24, çözülen özet de
  yazılınca 17/24, kaynak alanı her derlemede yazılınca 24/24. Bedeli imaj başına 96 bayt ve
  kayda tek alandır.

## Sonraki Adım

Bu dersin ölçümü bir şeyi sessizce varsaydı: manifestteki her satırın karşılığı bir yerde
duruyor. O yer hiç ölçülmedi. On dokuz taşımada değişen 141,7 MB'nin karşılığında değişmeyen
513,8 MB vardır ve bu baytların kaç kopya olduğu katmanların paylaşılıp paylaşılmadığına bağlıdır.

Sonraki ders o yeri kurar ve sayar: aynı katmanı birden çok imaj referans ettiğinde depo gerçekte
ne kadar büyüyor, bir imaj silindiğinde kaç katman gerçekten silinebiliyor, saklama kuralı katman
referanslarına çarptığında ne oluyor ve yerelde zaten bulunan katman atlandığında indirilen bayt
ne kadar düşüyor?
