---
title: 'İmaj Tanım Dosyası'
source: 'https://academia.sh/tr/kurslar/konteynerler/imaj-tanim-dosyasi'
course: Konteynerler
language: tr
updated: '2026-08-17T18:09:04+00:00'
license: 'CC BY-SA 4.0'
---

# İmaj Tanım Dosyası

Katmanların elle değil yönergelerden doğduğu ölçülür: beş yönergelik bir tanım dosyası biçimi tanımlanır, yönergeleri sırayla uygulayan bir yorumlayıcı yazılır ve derleme bağlamının büyüklüğü sayılır — ağaca giren dosya ve bayt, dışlama kuralının kestiği pay ve bağlamda olup imaja hiç girmeyen dosyalar.

Önceki dersin katmanları elle tanımlanmıştı: hangi dosyanın hangi katmana gireceği bir nesne
sabitinde yazılıydı. Bu, ölçümü yapmaya yetiyordu ama bir imajın nasıl kurulduğunu anlatmıyordu.
Gerçek bir imaj, sırayla uygulanan **yönergelerden** doğar; her yönerge bir öncekinin üstüne bir
katman koyar ve sonuncusu bittiğinde imaj hazırdır.

Bu ders o yönergeleri ve yönergelerin beslendiği kümeyi ölçer. Kopyalanacak dosyalar bir yerden
gelir: yönergelerin okuyabileceği dosya kümesine **derleme bağlamı** denir ve bağlamın büyüklüğü
bir bedeldir. Ölçülecek üç sayı vardır — bağlama kaç dosya ve kaç bayt girer, dışlama kuralı kaç
dosyayı ve kaç baytı keser, bağlama girip imaja hiç ulaşmayan kaç dosya kalır?

**IM7.** Aşağıdaki yönerge kümesi ve tanım dosyası biçimi bu ders için tanımlanmıştır; beş
yönergeden oluşur ve gerçek imaj tanım dosyası biçimlerinden çok daha küçüktür. Yorumlayıcı `node`
ile yazılan bir modeldir. **IM8.** `calistir` yönergesi gerçek bir komut çalıştırmaz; modellenmiş
bir komut tablosundan dosya üretir — bağımlılık kurulumunun çıktısı böyle temsil edilir.
**IM9.** Ağaç, kurgudaki bölgesel ölçüm ağının okuma toplayıcı servisinin kaynak ağacıdır; dosya
içerikleri satır sayısıyla ölçeklenmiş üretilmiş metindir. **IM10.** Dışlama kuralı önek
eşleşmesiyle çalışır; gerçek kurallar desen dili kullanır, bu ölçümün sayılarını değiştirmez.

## Beş Yönerge

Tanım dosyası bir metin dosyasıdır ve her satırı bir yönergedir. Yönergeler sırayla uygulanır;
sıra, önceki dersin yığın sırasının aynısıdır — altta duran önce çalışır.

| Yönerge | Ne yapar | Katman üretir mi |
|---|---|---|
| `temel` | Yığının en altına bir başlangıç dosya kümesi koyar | evet |
| `kopyala` | Derleme bağlamından bir yolu imajın içine kopyalar | evet |
| `calistir` | Bir komut çalıştırıp ürettiği dosyaları katman yapar | evet |
| `ayar` | İmajın üstverisine bir değer yazar | hayır |
| `giris` | Konteyner başladığında çalışacak yolu üstveriye yazar | hayır |

Son iki yönerge dosya sistemine dokunmaz; imajın **üstverisini** yazar. Ayrım ölçülecektir: bir
imajın katman sayısı, tanım dosyasının satır sayısı değildir.

## Derleme Bağlamı

Ağaç diske kurulur ve dışlama kuralının ne kestiği sayılır. Bağlam, yönergelerin okuyabileceği
kümedir; dışlama kuralına takılan bir yol, hiçbir yönerge onu istemese bile okunmaz.

```js
// olcum-agi/proje.mjs — kurgu servisin kaynak agacini diske kurar, derleme baglamini olcer
import { mkdirSync, writeFileSync, readdirSync, readFileSync, rmSync } from "node:fs";

export const KOK = "proje";
export const metin = (ad, satir) => Array.from({ length: satir }, (_, i) => `// ${ad} ${i}\n`).join("");

export const TANIM = `temel     kosum-tabani
kopyala   ayar/bolge.json  /uygulama/ayar/bolge.json
calistir  bagimlilik-kur
kopyala   kaynak           /uygulama/kaynak
ayar      BOLGE=kuzey
giris     /uygulama/kaynak/giris.js
`;

const AGAC = {
  "imaj-tanimi": TANIM,
  "ayar/bolge.json": '{"bolge":"kuzey","sayac":41820}\n',
  "ayar/yerel.json": '{"kapi":8080,"kutuk":"ayrintili"}\n',
  "kaynak/giris.js": metin("giris", 20),
  "kaynak/topla.js": metin("topla", 140),
  "kaynak/kuyruk.js": metin("kuyruk", 95),
  "kaynak/sinama/topla.sinama.js": metin("sinama-topla", 210),
  "kaynak/sinama/kuyruk.sinama.js": metin("sinama-kuyruk", 160),
  "bagimlilik/csv/dizin.js": metin("csv", 900),
  "bagimlilik/kuyruk/dizin.js": metin("kuyruk-bag", 1400),
  "belge/mimari.md": metin("belge", 240),
  "gunluk/kosum-1873.log": metin("gunluk", 2600),
  "yapi-artigi/paket-onceki.js": metin("artik", 1100),
  ".yerel-ayar/duzenleyici.json": metin("duzenleyici", 12),
  "okuma-ornekleri/gun-1.csv": metin("ornek", 380),
};

// Dislama kurali: bu oneklerle baslayan yollar baglama hic alinmaz.
export const DISLAMA = ["bagimlilik/", "gunluk/", "yapi-artigi/", ".yerel-ayar/", "belge/"];

export const kurAgac = () => {
  rmSync(KOK, { recursive: true, force: true });
  for (const [yol, icerik] of Object.entries(AGAC)) {
    mkdirSync(`${KOK}/${yol}`.split("/").slice(0, -1).join("/"), { recursive: true });
    writeFileSync(`${KOK}/${yol}`, icerik);
  }
};

export const gez = (kok, alt = "") =>
  readdirSync(`${kok}${alt}`, { withFileTypes: true }).flatMap((g) =>
    g.isDirectory() ? gez(kok, `${alt}/${g.name}`) : [`${alt}/${g.name}`.slice(1)]).sort();

export const bayt = (yol) => readFileSync(`${KOK}/${yol}`).length;
export const disarida = (yol, kural = DISLAMA) => kural.some((d) => yol.startsWith(d));
export const baglam = (kural = DISLAMA) => gez(KOK).filter((y) => !disarida(y, kural));
export const toplam = (yollar) => yollar.reduce((t, y) => t + bayt(y), 0);
```

```js
// olcum-agi/olcbaglam.mjs — agac, dislama ve baglam buyuklugu
import { kurAgac, gez, bayt, disarida, baglam, toplam, KOK, TANIM } from "./proje.mjs";

kurAgac();
const tumu = gez(KOK);
const kesilen = tumu.filter((y) => disarida(y));
console.log("imaj tanimi:\n" + TANIM);
console.log("ust dizin".padEnd(16) + "dosya   bayt   baglamda");
const grup = {};
for (const y of tumu) (grup[y.includes("/") ? y.split("/")[0] + "/" : "(kok)"] ??= []).push(y);
for (const [d, yollar] of Object.entries(grup))
  console.log(d.padEnd(16) + String(yollar.length).padStart(3) + String(toplam(yollar)).padStart(8) +
    "   " + (disarida(yollar[0]) ? "hayir" : "evet"));
console.log(`\nagac toplami    : ${tumu.length} dosya, ${toplam(tumu)} bayt`);
console.log(`dislama kesti   : ${kesilen.length} dosya, ${toplam(kesilen)} bayt`);
console.log(`derleme baglami : ${baglam().length} dosya, ${toplam(baglam())} bayt ` +
  `(agacin %${((toplam(baglam()) * 100) / toplam(tumu)).toFixed(1)} bayti)`);
```

```
imaj tanimi:
temel     kosum-tabani
kopyala   ayar/bolge.json  /uygulama/ayar/bolge.json
calistir  bagimlilik-kur
kopyala   kaynak           /uygulama/kaynak
ayar      BOLGE=kuzey
giris     /uygulama/kaynak/giris.js

ust dizin       dosya   bayt   baglamda
.yerel-ayar/      1     206   hayir
ayar/             2      66   evet
bagimlilik/       2   35280   hayir
belge/            1    3010   hayir
gunluk/           1   37890   hayir
(kok)             1     203   evet
kaynak/           5   10505   evet
okuma-ornekleri/  1    4830   evet
yapi-artigi/      1   14290   hayir

agac toplami    : 15 dosya, 106280 bayt
dislama kesti   : 6 dosya, 90676 bayt
derleme baglami : 9 dosya, 15604 bayt (agacin %14.7 bayti)
```

Ağaç **15 dosya ve 106 280 bayttır**; dışlama kuralı **6 dosya ve 90 676 baytı** keser, bağlama
**9 dosya ve 15 604 bayt** kalır — ağacın bayt olarak yüzde 14,7'si. Kesilen payın büyüklüğü
tesadüf değildir: bir kaynak ağacının hacminin çoğu kurulu bağımlılıklar, kütükler ve önceki yapı
artıklarıdır. Dışlama kuralı yazılmazsa bu 90 676 bayt her derlemede okunur ve bir sonraki dersin
ölçeceği önbellek kararına da girer.

Kuralın atladığı bir şey de sayıdadır: `okuma-ornekleri/` dizini bağlamda kalmıştır ve 4 830 bayt
taşır. Dışlama kuralı yalnız yazıldığı yolları keser; yazılmayan her yol bağlamdadır.

## Yorumlayıcı

Yorumlayıcı tanım dosyasını satır satır okur, her satır için ayrı bir katman dizini açar ve
yönergeyi o dizine uygular. Kopyalanan yolların kaydı tutulur; ölçümün sonundaki fark buradan
çıkar.

```js
// olcum-agi/yorumla.mjs — yonergeleri sirayla uygular, her yonergeden bir katman uretir (model)
import { mkdirSync, writeFileSync, readFileSync, rmSync, statSync } from "node:fs";
import { gez, disarida, metin, DISLAMA, KOK } from "./proje.mjs";

const TABAN = { "kok/kabuk.js": metin("kabuk", 60), "kok/kosum.js": metin("kosum", 420) };
const KOMUT = { "bagimlilik-kur": { "uygulama/bagimlilik/csv.js": metin("csv-kurulu", 900),
  "uygulama/bagimlilik/kuyruk.js": metin("kuyruk-kurulu", 1400) } };
const yaz = (dizin, dosyalar) => {
  for (const [yol, icerik] of Object.entries(dosyalar)) {
    mkdirSync(`${dizin}/${yol}`.split("/").slice(0, -1).join("/"), { recursive: true });
    writeFileSync(`${dizin}/${yol}`, icerik);
  }
};

export const derle = (tanim, kural = DISLAMA) => {
  rmSync("imaj", { recursive: true, force: true });
  const okunan = new Set(), ustveri = {}, katmanlar = [];
  tanim.trim().split("\n").forEach((satir, i) => {
    const [yonerge, ...arg] = satir.trim().split(/\s+/);
    const dizin = `imaj/kat-${i}`;
    mkdirSync(dizin, { recursive: true });
    if (yonerge === "temel") yaz(dizin, TABAN);
    else if (yonerge === "calistir") yaz(dizin, KOMUT[arg[0]]);
    else if (yonerge === "kopyala") {
      const [kaynak, hedef] = arg;
      const tekil = !statSync(`${KOK}/${kaynak}`).isDirectory();
      const bas = tekil || kaynak === "." ? "" : `${kaynak}/`;
      const alt = (tekil ? [kaynak] : gez(KOK, bas ? `/${kaynak}` : "")).filter((y) => !disarida(y, kural));
      for (const y of alt) {
        const ic = `${dizin}/${hedef.slice(1)}` + (tekil ? "" : `/${y.slice(bas.length)}`);
        mkdirSync(ic.split("/").slice(0, -1).join("/"), { recursive: true });
        writeFileSync(ic, readFileSync(`${KOK}/${y}`));
        okunan.add(y);
      }
    } else ustveri[yonerge] = arg.join(" ");
    const yollar = gez(dizin);
    katmanlar.push({ sira: i, yonerge, arg: arg.join(" "), dosya: yollar.length,
      bayt: yollar.reduce((t, y) => t + statSync(`${dizin}/${y}`).size, 0) });
  });
  return { katmanlar, okunan, ustveri };
};
```

```js
// olcum-agi/olcyorum.mjs — yorumlayiciyi kosturur, baglam ile imaj arasindaki farki sayar
import { derle } from "./yorumla.mjs";
import { kurAgac, baglam, toplam, TANIM } from "./proje.mjs";

kurAgac();
const { katmanlar, okunan, ustveri } = derle(TANIM);
console.log("sira yonerge   arguman".padEnd(58) + "tur          dosya   bayt");
for (const k of katmanlar)
  console.log(`  ${k.sira}  ${k.yonerge.padEnd(9)} ${k.arg}`.padEnd(58) +
    (k.dosya ? "dosya sistemi" : "ustveri      ") + String(k.dosya).padStart(4) + String(k.bayt).padStart(8));

const dosyaKatmani = katmanlar.filter((k) => k.dosya > 0);
const imajBayt = dosyaKatmani.reduce((t, k) => t + k.bayt, 0);
const girmeyen = baglam().filter((y) => !okunan.has(y));
const sinama = [...okunan].filter((y) => y.includes("/sinama/"));
console.log(`\nustveri: ${JSON.stringify(ustveri)}`);
console.log(`imaj: ${dosyaKatmani.length} dosya sistemi katmani, ${katmanlar.length - dosyaKatmani.length} ustveri yonergesi, ${imajBayt} bayt`);
console.log(`baglamdan okunan ${okunan.size} dosya, ${toplam([...okunan])} bayt`);
console.log(`baglamda olup imaja hic girmeyen ${girmeyen.length} dosya, ${toplam(girmeyen)} bayt: ${girmeyen.join(" ")}`);
console.log(`imaja giren ama kosumda gerekmeyen ${sinama.length} dosya, ${toplam(sinama)} bayt`);
console.log(`derleme baglami ${toplam(baglam())} bayt okundu, imaja ${toplam([...okunan])} bayt gecti`);
```

```
sira yonerge   arguman                                    tur          dosya   bayt
  0  temel     kosum-tabani                               dosya sistemi   2    6060
  1  kopyala   ayar/bolge.json /uygulama/ayar/bolge.json  dosya sistemi   1      32
  2  calistir  bagimlilik-kur                             dosya sistemi   2   45780
  3  kopyala   kaynak /uygulama/kaynak                    dosya sistemi   5   10505
  4  ayar      BOLGE=kuzey                                ustveri         0       0
  5  giris     /uygulama/kaynak/giris.js                  ustveri         0       0

ustveri: {"ayar":"BOLGE=kuzey","giris":"/uygulama/kaynak/giris.js"}
imaj: 4 dosya sistemi katmani, 2 ustveri yonergesi, 62377 bayt
baglamdan okunan 6 dosya, 10537 bayt
baglamda olup imaja hic girmeyen 3 dosya, 5067 bayt: ayar/yerel.json imaj-tanimi okuma-ornekleri/gun-1.csv
imaja giren ama kosumda gerekmeyen 2 dosya, 7340 bayt
derleme baglami 15604 bayt okundu, imaja 10537 bayt gecti
```

Altı satırlık tanım dosyası **dört** dosya sistemi katmanı üretir; iki satır yalnız üstveri yazar
ve yığına hiçbir bayt eklemez. Önceki dersin ölçüsüyle söylenirse: `ayar` ve `giris` satırlarının
değiştirilmesi hiçbir katmanın içerik özetini değiştirmez, çünkü ortada katman yoktur.

## Bağlama Girip İmaja Girmeyen

Üç sayı yan yana konduğunda tanım dosyasının asıl maliyeti görünür. Bağlam **15 604 bayttır**,
bağlamdan okunan **10 537 bayttır**, imaj **62 377 bayttır**. Üçü de farklıdır ve farkların
her biri ayrı bir şey söyler.

Bağlam ile okunan arasındaki fark **3 dosya ve 5 067 bayttır**: yerel ayar dosyası, tanım
dosyasının kendisi ve örnek okuma verisi bağlama girer, hiçbir yönerge onları istemez, imaja hiç
ulaşmazlar. Yine de derleme adımının okuma erişimindedirler — bağlamda olmak, imaja girmekten
bağımsız bir izindir. Bu, dışlama kuralının yalnız boyut için yazılmadığını gösterir.

Okunan ile imaj arasındaki fark ters yöndedir: imaj bağlamdan aldığından **beş kat** büyüktür.
Farkın kaynağı `calistir` yönergesidir; tek satır **45 780 bayt** üretir, imajın yüzde 73'ü o
katmandır. Dışlama kuralının kestiği 35 280 baytlık bağımlılık ağacı imajdan çıkmış değildir,
**kaynağı değişmiştir**: yazan kişinin makinesinde kurulmuş hâliyle kopyalanmak yerine yönergenin
kendisi tarafından üretilir. Ortamdan çıkarılan fark budur — kurulu bağımlılıkların sürümü artık
bir makinenin durumu değil, tanım dosyasının bir satırıdır.

Bedelin son kalemi `kopyala kaynak` satırındadır. Bir dizin kopyalandığında içine ne girdiğini
yönerge söylemez: sınama dosyaları da imaja girer, **2 dosya ve 7 340 bayt**, imajın koşumda
gerekmeyen yüzde 11,8'i. Yönerge dosya değil dizin adı taşıdığı için bu, tanım dosyasına bakarak
görülemez; ancak katman içeriği sayılarak görülür. Yalıtımın eksik kaldığı yer burasıdır: imaj
**neyin gerektiğini** değil, **neyin kopyalandığını** kaydeder.

## Seçici Kopyalama ile Bağlamı Kopyalamak

Yönergenin ne kadarını seçtiği bir karardır ve karar üç biçimde sayılabilir. **IM11.** İkinci bir
tanım dosyası tüm bağlamı tek yönergeyle kopyalar; üçüncü ölçüm aynı tanımı dışlama kuralı boşken
koşturur. **IM12.** Koşumda gereken dosyalar açıkça listelenir: sınama dizini dışındaki kaynak
dosyaları ve bölge ayarı. Geri kalan her şey imaja girdiyse gereksizdir.

```js
// olcum-agi/genis.mjs — secici kopyalama ile tum baglami kopyalamayi karsilastirir
import { derle } from "./yorumla.mjs";
import { kurAgac, toplam, TANIM } from "./proje.mjs";

const GENIS = `temel     kosum-tabani
kopyala   .  /uygulama
calistir  bagimlilik-kur
giris     /uygulama/kaynak/giris.js
`;

const GEREKLI = (y) => (y.startsWith("kaynak/") && !y.includes("/sinama/")) || y === "ayar/bolge.json";

kurAgac();
const olc = (etiket, tanim, kural) => {
  const { katmanlar, okunan } = derle(tanim, kural);
  const k = katmanlar.filter((x) => x.dosya > 0);
  const gereksiz = [...okunan].filter((y) => !GEREKLI(y));
  console.log(etiket.padEnd(30) + String(k.length).padStart(2) + String(k.reduce((t, x) => t + x.dosya, 0)).padStart(7) +
    String(k.reduce((t, x) => t + x.bayt, 0)).padStart(9) + String(gereksiz.length).padStart(9) +
    String(toplam(gereksiz)).padStart(8));
};
console.log("tanim".padEnd(30) + "kat  dosya     bayt  gereksiz   bayt");
olc("secici kopyalama", TANIM);
olc("tum baglam, dislama var", GENIS);
olc("tum baglam, dislama yok", GENIS, []);
```

```
tanim                         kat  dosya     bayt  gereksiz   bayt
secici kopyalama               4     10    62377        2    7340
tum baglam, dislama var        3     13    67444        5   12407
tum baglam, dislama yok        3     19   158120       11  103083
```

Üç satır aynı uygulamayı üretir ve boyutları **62 377**, **67 444** ve **158 120** bayttır. İlk
iki satır arasındaki fark küçüktür — 5 067 bayt — çünkü dışlama kuralı zaten ağır dizinleri
kesmiştir. Üçüncü satırda kural boşaltıldığında imaj **2,5 kat** büyür ve içindeki gereksiz dosya
sayısı ikiden **on bire**, gereksiz bayt 7 340'tan **103 083**'e çıkar. İmajın üçte ikisi
çalıştırılmayacak dosyalardan oluşur: kütükler, önceki yapı artıkları, belgeler ve yerel ayar.

İki tanımın katman sayısı da farklıdır: seçici tanım dört, geniş tanım üç dosya sistemi katmanı
üretir. Daha az katman burada iyi bir sonuç değildir — geniş tanımda kaynak ile ayar aynı
yönergeye girdiği için ayrı katmanlara ayrılamamıştır, üstelik bağımlılık kurulumundan **önce**
kopyalanmıştır. Bu iki ayrıntının bedeli bu derste görünmez; sonraki dersin ölçtüğü şey tam olarak
odur.

## Özet

- İmaj tanım dosyası bir yönerge dizisidir; yönergeler sırayla uygulanır ve her biri bir öncekinin
  üstüne katman koyar. Altı satırlık tanım dört dosya sistemi katmanı üretti, iki satır yalnız
  üstveri yazdı — katman sayısı satır sayısı değildir.
- Derleme bağlamı, yönergelerin okuyabileceği dosya kümesidir. 15 dosyalık 106 280 baytlık ağaçtan
  dışlama kuralı 6 dosya ve 90 676 baytı kesti; bağlama 9 dosya ve 15 604 bayt kaldı.
- Bağlamda olup imaja hiç girmeyen 3 dosya ve 5 067 bayt sayıldı. Bağlamda olmak imaja girmekten
  ayrı bir izindir; dışlama kuralı yalnız boyut için yazılmaz.
- `calistir` yönergesi tek satırda 45 780 bayt üretti — imajın yüzde 73'ü. Dışlanan bağımlılık
  ağacı imajdan çıkmadı, kaynağı bir makinenin durumundan tanım dosyasının bir satırına geçti.
- Dizin kopyalayan yönerge 2 sınama dosyasını ve 7 340 baytı imaja soktu. İmaj neyin gerektiğini
  değil neyin kopyalandığını kaydeder; fark ancak katman içeriği sayılarak görünür.
- Aynı uygulama üç tanımla derlendiğinde imaj 62 377, 67 444 ve 158 120 bayt çıktı. Dışlama kuralı
  boşken tüm bağlamı kopyalayan tanım imajı 2,5 katına çıkardı ve içindeki gereksiz dosya sayısını
  ikiden on bire taşıdı.

## Sonraki Adım

Bu ölçüm tek bir derlemeyi saydı. Yönergeler her derlemede baştan uygulandığında `calistir`
satırının ürettiği 45 780 bayt da her seferinde yeniden üretilir — oysa bağımlılık listesi
değişmediyse çıktısı da değişmez. Katmanların içerik özetiyle adlandığı bilindiğine göre, değişmemiş
bir yönergenin katmanı yeniden üretilmek yerine saklanandan alınabilir. Sonraki ders bu saklamayı
kurar ve tek bir kararın sayısını verir: bağımlılık kurulumu ile kaynak kopyalamanın hangi sırada
yazıldığı, aynı değişiklik dizisinde önbellek isabet oranını, yeniden üretilen katman sayısını ve
kopyalanan toplam baytı ne kadar oynatır?
