File System & Layer #
Hampir semua orang yang menggunakan Docker tahu dua hal: image itu immutable, dan container itu ephemeral. Tapi sangat sedikit yang benar-benar paham mengapa kedua sifat itu muncul. Jawabannya ada di satu tempat — filesystem berlapis yang dipakai Docker di bawah permukaan.
Tanpa memahami layered filesystem, kamu akan terus menulis Dockerfile yang image-nya membengkak, build yang lambat, dan deploy yang tidak konsisten. Dengan memahaminya, kamu bisa menulis Dockerfile yang ramping, build yang cepat, dan storage yang efisien di production.
Artikel ini membongkar fondasi storage Docker dari bawah: union filesystem, image layer, container writable layer, copy-on-write, dan bagaimana semuanya bekerja sama. Tujuannya bukan supaya kamu hafal istilah, tapi supaya kamu punya model mental yang benar tentang apa yang sebenarnya terjadi setiap kali kamu menjalankan docker build atau docker run.
Mengapa Storage Docker Penting Dipahami #
Container sering digambarkan sebagai “mesin virtual yang ringan”, tapi analogi itu menyesatkan. Container bukan VM mini. Ia tidak membawa filesystem sendiri, tidak punya disk image, dan tidak melakukan provisioning disk saat start. Yang ia lakukan adalah mengikat (bind) banyak layer filesystem read-only menjadi satu mount point, lalu menambahkan satu layer writable di atasnya saat runtime.
flowchart TB
subgraph IMG["Image — Read-Only Layers"]
L1[Base Image Layer<br/>ubuntu:22.04 — 77 MB]
L2[apt install nginx — 50 MB]
L3[COPY config — 0.1 MB]
L4[CMD nginx — 0 MB]
L1 --> L2 --> L3 --> L4
end
L4 --> UNION[Union Mount<br/>filesystem yang dilihat container]
UNION --> RUNTIME[Container Writable Layer<br/>perubahan runtime — top layer]
Struktur ini punya tiga konsekuensi besar yang akan kamu temui di seluruh seri storage ini:
- Image kecil, cache tinggi. Layer yang sama dipakai bersama banyak image. Build inkremental hanya men-download layer yang berubah.
- Container cepat start. Tidak ada copy filesystem saat start. Yang ditambahkan hanya satu writable layer kosong.
- Container mudah hilang. Writable layer adalah satu-satunya tempat perubahan runtime — dan ia ikut mati saat container dihapus.
Ketiga konsekuensi ini menentukan semua keputusan storage lain yang akan kamu pelajari di artikel-artikel selanjutnya: kenapa volume dibutuhkan, kenapa data harus dipisahkan, dan kenapa backup berfokus pada data, bukan container.
Apa Itu Docker Filesystem? #
Docker tidak membuat filesystem baru dari nol untuk setiap image. Docker memanfaatkan filesystem Linux yang sudah matang untuk melakukan dua hal:
- Union mount — menggabungkan banyak direktori menjadi satu tampilan tunggal.
- Copy-on-write (CoW) — menduplikasi blok hanya saat ada perubahan.
Kombinasi keduanya adalah inti dari seluruh sistem storage Docker. Ia membuat image bisa kecil, container bisa start cepat, dan banyak container bisa berbagi layer yang sama tanpa duplikasi di disk.
flowchart LR
A[Image Layer A] --> U[Union View]
B[Image Layer B] --> U
C[Image Layer C] --> U
U --> CON[Container melihat<br/>satu filesystem utuh]
Filesystem inilah yang membuat Docker image bersifat immutable (tidak bisa berubah) dan container bersifat ephemeral (sementara). Dua sifat ini bukan fitur tambahan — ia adalah konsekuensi langsung dari cara layer disusun.
Detail menarik: Union filesystem adalah salah satu teknologi yang membuat Docker benar-benar praktis. Tanpa ini, setiap perubahan kode akan mengharuskan build image dari awal dan re-download semua dependency. Dengan layering, build inkremental di Docker biasanya hanya butuh detik.
Jenis-Jenis Storage Driver #
Docker tidak menentukan satu implementasi union filesystem. Ia menyediakan abstraksi storage driver yang bisa memilih implementasi sesuai OS dan kondisi host.
| Storage Driver | Status | Use Case |
|---|---|---|
overlay2 |
Default & direkomendasikan | Linux modern (kernel 4.0+) |
btrfs |
Supported | Host filesystem Btrfs |
zfs |
Supported | Host filesystem ZFS |
fuse-overlayfs |
Supported | Rootless container |
vfs |
Fallback | Tidak ada CoW (testing only) |
aufs |
Legacy | Tidak direkomendasikan untuk instalasi baru |
devicemapper |
Deprecated | RHEL lama, CentOS 7 |
overlay2 adalah default di semua distribusi Linux modern dan pilihan yang direkomendasikan oleh Docker. Ia stabil, cepat, hemat memori, dan didukung penuh oleh komunitas. Kecuali kamu punya alasan spesifik, gunakan overlay2.
Cek driver yang sedang dipakai di host kamu:
docker info | grep "Storage Driver"
Output yang diharapkan:
Storage Driver: overlay2
Hindari driver legacy.aufssudah tidak dikembangkan dan hanya ada di kernel lama.devicemappersudah deprecated di Docker modern. Jika kamu menemukannya di server production, pertimbangkan migrasi ke host denganoverlay2— driver legacy bisa menimbulkan masalah performa dan stabilitas yang sulit di-debug.
Konsep Union Filesystem #
Union filesystem adalah teknologi yang memungkinkan beberapa direktori di-mount bersamaan di satu path, sehingga pengguna (atau container) melihatnya sebagai satu filesystem utuh.
Contoh konseptual:
Layer A: /app/main.go
Layer B: /app/config.yaml
Union View di /app:
/app/main.go ← dari Layer A
/app/config.yaml ← dari Layer B
Docker menggunakan konsep ini untuk menumpuk image layer dan menampilkannya sebagai satu filesystem ke container. Container tidak tahu ada berapa layer di belakangnya — yang ia lihat adalah satu pohon direktori yang utuh.
Cara Kerja di Overlay2 #
Untuk memahami implementasi nyata, perhatikan struktur internal overlay2:
flowchart TB
subgraph HOST["Host Filesystem"]
LOWER[/var/lib/docker/overlay2/.../diff<br/>LOWERDIR — read-only]
UPPER[/var/lib/docker/overlay2/.../diff<br/>UPPEDIR — writable, per container]
WORK[/var/lib/docker/overlay2/.../work<br/>WORKDIR — internal atomic ops]
MERGED[/var/lib/docker/overlay2/.../merged<br/>MERGED — view untuk container]
end
LOWER --> MERGED
UPPER --> MERGED
WORK -.-> UPPER
- Lowerdir — kumpulan image layer (read-only). Dipakai bersama oleh banyak container.
- Upperdir — writable layer milik satu container. Di sinilah perubahan runtime disimpan.
- Workdir — direktori internal yang digunakan kernel untuk operasi atomic saat copy-up.
- Merged — hasil union yang dilihat oleh container saat membaca path.
Container tidak pernah langsung mengakses lowerdir atau upperdir. Ia hanya melihat merged — satu filesystem utuh yang merupakan gabungan keduanya.
Apa Itu Layer di Docker? #
Layer adalah snapshot filesystem yang bersifat read-only. Setiap layer merepresentasikan satu perubahan filesystem — biasanya satu instruksi di Dockerfile.
Contoh Dockerfile:
FROM alpine:3.19
RUN apk add --no-cache curl
COPY app.sh /app.sh
CMD ["sh", "/app.sh"]
Layer yang terbentuk:
- Base layer — Alpine Linux 3.19 (~7 MB).
- Layer RUN — hasil instalasi
curl(~1 MB). - Layer COPY — file
app.sh(~0.01 MB). - Layer CMD — tidak menambah filesystem (instruksi metadata, bukan data).
Setiap layer:
- Immutable — tidak bisa diubah setelah dibuat. Konten layer di-hash (SHA256) dan hash itu jadi identitas layer.
- Reusable — bisa dipakai bersama oleh image lain yang punya instruksi identik.
- Cacheable — Docker build cache melihat layer berdasarkan hash instruksi + konteks. Jika tidak berubah, layer dipakai ulang dari cache.
flowchart TB
A[FROM alpine:3.19] --> B[RUN apk add curl]
B --> C[COPY app.sh /app.sh]
C --> D[CMD app.sh]
A -.->|Layer 1: base alpine| LA[alpine-base.tar]
B -.->|Layer 2: apk result| LB[curl-install.tar]
C -.->|Layer 3: app.sh| LC[app-sh.tar]
D -.->|Metadata| LD[cmd-meta.json]
Layer dan Dockerfile #
Prinsip krusial yang harus kamu pegang:
Satu instruksi Dockerfile = satu layer baru (untuk instruksi yang mengubah filesystem).
| Instruksi | Membuat Layer? | Alasan |
|---|---|---|
FROM |
Ya | Menarik base image (beberapa layer) |
RUN |
Ya | Eksekusi command yang menghasilkan perubahan filesystem |
COPY |
Ya | Menambahkan file ke image |
ADD |
Ya | Sama seperti COPY, plus fitur ekstrak tar & URL |
CMD |
Tidak | Hanya metadata default command |
ENTRYPOINT |
Tidak | Hanya metadata executable |
ENV |
Tidak | Environment variable, tidak menambah file |
WORKDIR |
Tidak | Hanya mengubah direktori kerja |
EXPOSE |
Tidak | Hanya metadata port |
LABEL |
Tidak | Hanya metadata key-value |
ARG |
Tidak | Build-time variable |
USER |
Tidak | Mengubah user context, tidak menambah file |
VOLUME |
Tidak | Mendeklarasikan mount point |
Implikasinya langsung: urutan instruksi di Dockerfile sangat berpengaruh pada ukuran image dan kecepatan build. Setiap RUN, COPY, dan ADD menambah layer permanen di image final.
Copy-on-Write — Kunci Efisiensi Docker #
Docker menggunakan mekanisme copy-on-write (CoW) saat container berjalan. CoW adalah optimasi: file hanya disalin saat ada upaya untuk mengubahnya, bukan saat dibaca.
Alurnya:
- Container membaca file → langsung dari image layer (lowerdir), tidak ada copy.
- Container mengubah file → file disalin dari lowerdir ke upperdir (writable layer), lalu diubah di sana.
- Perubahan hanya terjadi di upperdir — image layer tetap utuh dan bisa dipakai container lain.
flowchart TB
subgraph READ["Container baca /etc/nginx.conf"]
R1[Request baca] --> R2{File ada<br/>di upperdir?}
R2 -- Tidak --> R3[Baca langsung<br/>dari lowerdir]
R2 -- Ya --> R4[Baca dari upperdir]
end
subgraph WRITE["Container tulis /etc/nginx.conf"]
W1[Request tulis] --> W2{File ada<br/>di upperdir?}
W2 -- Tidak --> W3[COPY-UP<br/>copy file ke upperdir]
W2 -- Ya --> W4[Modifikasi di upperdir]
W3 --> W4
end
Keuntungan CoW untuk Performa #
- Read cepat — file yang tidak berubah langsung dibaca dari image layer. Tidak ada overhead.
- Write hanya saat perlu — container yang hanya membaca konfigurasi tidak pernah memicu copy.
- Image tetap aman — perubahan runtime tidak pernah menyentuh image layer asli. Image selalu bisa di-reuse.
- Container terisolasi — setiap container punya upperdir sendiri, sehingga perubahan di satu container tidak memengaruhi container lain yang dari image sama.
Insight praktis: Ini menjelaskan kenapa container start dalam detik, bukan menit. Saat docker run dieksekusi, Docker tidak menyalin filesystem image. Ia hanya membuat upperdir kosong dan me-mount union. Pekerjaan copy baru benar-benar terjadi saat aplikasi pertama kali menulis file — dan bahkan itu pun lazy.
Writable Layer pada Container #
Saat container dibuat dari image, Docker menambahkan satu writable layer di atas semua image layer. Layer ini sering disebut container layer atau runtime layer.
Karakteristiknya:
- Unik per container — setiap container dari image yang sama punya upperdir sendiri.
- Bersifat sementara — hilang saat container dihapus.
- Tidak cocok untuk data permanen — karena sifatnya yang sementara, menyimpan data penting di sini adalah anti-pattern.
flowchart TB
subgraph SHARED["Shared Image Layers (read-only)"]
L1[Base]
L2[RUN]
L3[COPY]
end
subgraph C1["Container A"]
L1 --> UA[Upperdir A<br/>writable]
L2 --> UA
L3 --> UA
end
subgraph C2["Container B"]
L1 --> UB[Upperdir B<br/>writable]
L2 --> UB
L3 --> UB
end
SHARED --> C1
SHARED --> C2
Ini menjelaskan banyak perilaku Docker yang sering membuat bingung:
- Mengapa
docker commitbisa membuat image baru? Karenadocker commitmembekukan upperdir menjadi image layer baru. Isi upperdir menjadi layer di image baru. - Mengapa data MySQL hilang saat container dihapus? Karena
/var/lib/mysqlada di upperdir, dan upperdir ikut hilang saat container dihapus. - Mengapa
docker rundari image yang sama sangat cepat? Karena image layer tidak disalin. Hanya upperdir kosong yang dibuat.
Inilah alasan volume dan bind mount menjadi sangat penting di Docker — ia memindahkan data dari upperdir ke filesystem host, sehingga data tetap ada walau container hancur.
Anti-pattern kritis: Jangan pernah menyimpan data penting di writable layer container. Database, file upload user, log aplikasi, dan konfigurasi runtime harus selalu berada di volume atau bind mount. Writable layer akan hilang saat container dihapus, di-restart dengan image baru, atau di-recreate oleh orchestrator. Ini adalah sumber data loss paling umum di Docker.
Image Bersifat Immutable #
Karena layer image bersifat read-only, image tidak bisa diubah setelah build. Setiap perubahan menghasilkan image baru. Ini mungkin terdengar sebagai keterbatasan, tapi sebenarnya adalah fitur kekuatan Docker.
Keuntungan immutability:
- Build reproducible — image yang sama selalu menghasilkan container yang sama. Tidak ada “configuration drift” misterius.
- Rollback mudah — jika image baru bermasalah, cukup kembali ke tag lama. Tidak perlu uninstall atau reconfigure.
- Konsisten antar environment — image yang sama berjalan identik di laptop developer, CI, staging, dan production.
- Audit-friendly — konten image bisa di-inspect (mis. dengan
docker history) dan di-hash untuk verifikasi integritas. - Cache friendly — layer image yang sama dipakai bersama, sehingga deployment tidak perlu download image dari nol.
Konsep ini adalah pondasi dari beberapa workflow penting di industri:
- CI/CD — image Docker menjadi build artifact yang sama dari pipeline sampai production.
- GitOps — image tag adalah reference yang bisa di-version di Git (mis.
:v1.2.3). - Immutable infrastructure — server (atau container) yang berjalan tidak di-patch di tempat, tapi di-replace dengan instance baru dari image baru.
# Lihat history layer sebuah image
docker history nginx:1.25
# Output:
# IMAGE CREATED CREATED BY SIZE
# a4d8d7c4b1f0 3 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
# e9b1f5c0a2c3 3 weeks ago EXPOSE 80 0B
# ...
Layer Sharing dan Efisiensi Storage #
Docker menyimpan layer berdasarkan hash konten (SHA256). Jika dua image memiliki layer dengan konten identik, layer itu hanya disimpan satu kali di disk dan dipakai bersama.
Contoh dampak:
| Skenario | Tanpa Sharing | Dengan Layer Sharing |
|---|---|---|
10 image berbasis alpine:3.19 |
10 × 7 MB = 70 MB | 7 MB (1 layer dipakai bersama) |
5 image dengan apt install curl identik |
5 × 1 MB = 5 MB | 1 MB (1 layer dipakai bersama) |
| 50 microservice dengan base image sama | 50 × base size | 1 × base size |
Inilah alasan Docker hemat storage di skala besar. Bayangkan kamu punya 50 microservice di registry, semua berbasis node:20-alpine. Tanpa sharing, base layer di-download dan disimpan 50 kali. Dengan sharing, hanya 1 kali.
flowchart LR
subgraph REG["Docker Host Disk"]
B[alpine-base.tar<br/>7 MB]
C[curl-install.tar<br/>1 MB]
end
IMG1[Image: app1] --> B
IMG1 --> C
IMG2[Image: app2] --> B
IMG2 --> C
IMG3[Image: app3] --> B
IMG3 --> C
B -.satu salinan.-> REG
C -.satu salinan.-> REG
Implikasi praktis:
- Pull image lebih cepat — Docker hanya men-download layer yang belum ada di host.
- Push image ke registry lebih cepat — layer yang sudah ada di registry tidak perlu di-upload ulang.
- Storage host lebih efisien — layer bersama tidak diduplikasi.
Trik optimasi: Saat menulis Dockerfile, sengaja buat layer yang bisa di-share antar image. Misalnya, pisahkan instalasi system package (jarang berubah) dariCOPYsource code (sering berubah). Ini membuat layer system package di-cache lama dan hanya layerCOPYyang invalidate saat build.
Dampak Layer terhadap Build Performance #
Docker build cache bekerja berdasarkan konten layer. Cache key untuk setiap layer adalah hash dari:
- Isi instruksi Dockerfile.
- Hash dari parent layer.
- Untuk
COPY/ADD: hash konten file yang di-copy.
Jika semua itu cocok dengan build sebelumnya, layer dipakai dari cache. Jika salah satu berubah, layer di-build ulang, dan semua layer di bawahnya juga ikut di-rebuild.
Anti-Pattern: Copy Source Code Terlalu Dini #
# ANTI-PATTERN: source code di-copy sebelum dependency
FROM node:20-alpine
WORKDIR /app
COPY . . # ← perubahan 1 baris kode invalidate semua cache
RUN npm install # ← npm install dijalankan ulang setiap build
CMD ["node", "index.js"]
Masalah: setiap kali kamu mengubah satu baris kode di source, Docker membatalkan cache dari baris COPY . . ke bawah. Ini termasuk npm install, yang biasanya butuh waktu lama.
Solusi: Pisahkan Dependency dan Source Code #
# BENAR: dependency di-install dulu, source code belakangan
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./ # ← hanya invalidate saat package.json berubah
RUN npm install # ← cached selama package.json tidak berubah
COPY . . # ← invalidate setiap source code berubah
CMD ["node", "index.js"]
Hasil: perubahan source code tidak menjalankan npm install ulang. Build inkremental biasanya hanya butuh 1–2 detik.
flowchart LR
subgraph BAD["Anti-Pattern"]
B1[COPY . .] --> B2[RUN npm install]
B2 --> B3[perubahan kode<br/>→ npm install ulang]
end
subgraph GOOD["Best Practice"]
G1[COPY package.json] --> G2[RUN npm install]
G2 --> G3[COPY . .]
G3 --> G4[perubahan kode<br/>→ npm install cached]
end
Tips Tambahan untuk Build Cache #
Gunakan BuildKit (default di Docker modern) untuk fitur cache lanjutan:
- Cache mount — mount cache direktori ke build (
--mount=type=cache). Cache bertahan antar build. - Build cache ke registry — push/pull build cache dari Docker Hub atau ECR untuk CI yang berjalan di mesin fresh.
- Multi-stage build — pisahkan build artifact dari runtime image. Runtime image tidak membawa toolchain yang berat.
Aktifkan BuildKit:
# Di environment variable
export DOCKER_BUILDKIT=1
# Atau di Dockerfile (modern syntax)
# syntax=docker/dockerfile:1
Mount yang Perlu Kamu Ketahui #
Docker juga menyediakan tiga jenis mount yang bisa kamu tambahkan saat container berjalan. Ini relevan karena filesystem layer adalah pondasi, tapi volume dan bind mount adalah lapisan di atasnya untuk data persisten.
flowchart TB
subgraph TYPES["Jenis Mount di Docker"]
V[Volume<br/>dikelola Docker]
B[Bind Mount<br/>path host manual]
T[tmpfs<br/>disimpan di RAM]
end
V --> PERSIST[Data persisten<br/>untuk production]
B --> DEV[Live reload<br/>untuk development]
T --> SECRET[Sensitive data<br/>non-persistent]
Tiga jenis mount ini akan dibahas mendalam di artikel-artikel selanjutnya dalam section ini. Untuk sekarang, cukup pahami bahwa ketiganya beroperasi di atas layered filesystem yang sudah kita bahas — mereka tidak menggantikan image layer, tapi menambah data persistence di luarnya.
| Jenis Mount | Lokasi Fisik | Persisten? | Use Case Utama |
|---|---|---|---|
| Volume | /var/lib/docker/volumes/... |
Ya (dikelola Docker) | Database, upload, production data |
| Bind Mount | Path host sesuai yang kamu tentukan | Ya (tergantung host) | Source code untuk live reload, config |
| tmpfs | RAM | Tidak | Secret, session, cache sensitif |
Best Practice Filesystem dan Layer #
Prinsip-prinsip ini merangkum pelajaran dari seluruh artikel.
1. Minimalkan Jumlah Layer #
Gabungkan perintah yang terkait dalam satu RUN:
# BENAR: satu layer untuk install + cleanup
RUN apt-get update && \
apt-get install -y curl nginx && \
rm -rf /var/lib/apt/lists/*
# ANTI-PATTERN: banyak layer kecil
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y nginx
RUN rm -rf /var/lib/apt/lists/*
Versi pertama membuat 1 layer, versi kedua membuat 4 layer. Versi pertama juga menghapus cache apt di layer yang sama (penting untuk ukuran image), sedangkan versi kedua meninggalkannya di layer sebelumnya.
2. Urutkan Instruksi dengan Benar #
Letakkan yang paling jarang berubah di atas, yang paling sering berubah di bawah:
- Base image (paling jarang berubah).
- System package install (jarang berubah).
- Dependency install dari package manager (berubah saat dependency update).
- COPY source code (paling sering berubah).
- CMD/ENTRYPOINT (metadata, tidak menambah layer).
3. Gunakan Multi-Stage Build #
Untuk bahasa yang butuh toolchain saat build (Go, Rust, Java, TypeScript), pisahkan build environment dari runtime:
# Stage 1: build
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp
# Stage 2: runtime
FROM alpine:3.19
COPY --from=builder /app/myapp /myapp
CMD ["/myapp"]
Hasil: image runtime hanya 10–20 MB, bukan 800 MB seperti image build.
4. Pilih Base Image Sekecil Mungkin #
| Base Image | Ukuran | Use Case |
|---|---|---|
scratch |
0 MB | Binary statis (Go, Rust) |
alpine |
5–7 MB | Aplikasi ringan, butuh package manager |
distroless |
10–20 MB | Production Java/Node/Go, tanpa shell |
debian-slim |
30–50 MB | Butuh libc tapi ingin lebih kecil dari full |
ubuntu/debian |
70–120 MB | Default, tapi lebih besar dari perlu |
Untuk production, alpine atau distroless adalah pilihan terbaik. Untuk development, ubuntu atau debian lebih familiar.
5. Pahami Cache Layer Sebelum Optimasi #
Jangan asal menggabungkan layer. Setiap keputusan trade-off — antara cache hit dan ukuran image, antara jumlah layer dan kebersihan Dockerfile. Pahami implikasinya:
- Terlalu banyak layer → image besar.
- Terlalu sedikit layer → cache sering invalidate.
- Sweet spot → pisahkan yang jarang berubah (cached lama) dari yang sering berubah (cached pendek).
6. Bersihkan Artefak di Layer yang Sama #
Hapus cache package manager dan file temporary di RUN yang sama dengan instalasi:
# BENAR: hapus di layer yang sama
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# JANGAN: hapus di layer terpisah (file masih ada di layer sebelumnya)
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/* # ← ini tidak mengurangi ukuran image!
Kesalahan umum: Menghapus file diRUNterpisah tidak mengurangi ukuran image. Docker layer immutable — file yang ditambahkan di layer sebelumnya tetap ada. Untuk benar-benar menghapus, lakukan diRUNyang sama dengan pembuatan file.
Ringkasan #
- Docker image = kumpulan layer read-only yang digabung via union filesystem. Container menambahkan satu layer writable di atas saat runtime. Ini menjelaskan kenapa image kecil, container cepat start, dan data di container hilang saat dihapus.
- Storage driver default adalah
overlay2untuk Linux modern. Hindari driver legacy sepertiaufsdandevicemapperkecuali kamu punya alasan spesifik.- Copy-on-write (CoW) adalah mekanisme kunci: file hanya disalin ke writable layer saat ada perubahan. Read langsung dari image layer, write memicu copy-up.
- Image immutable karena layer read-only. Setiap perubahan menghasilkan image baru. Ini fitur, bukan keterbatasan — mendukung reproducible build, rollback, dan konsistensi environment.
- Layer sharing berdasarkan content hash. Image dengan layer identik berbagi storage di disk. Inilah kenapa Docker hemat ruang saat punya banyak image dari base yang sama.
- Build cache bekerja per-layer. Urutan Dockerfile sangat berpengaruh — letakkan yang jarang berubah di atas, yang sering berubah di bawah. Pisahkan
COPY package.jsondariCOPY . .untuk cachenpm installyang efektif.- Multi-stage build memisahkan build environment dari runtime image, menghasilkan image production yang kecil tanpa mengorbankan toolchain development.
- Jangan simpan data penting di writable layer container. Writable layer hilang saat container dihapus. Gunakan volume atau bind mount — topik artikel selanjutnya dalam section ini.
← Sebelumnya: Docker Use Case Berikutnya: Ephemeral Container →