Docker / Layer ба cache

Layer ба cache

Docker image нь давхарга (layer)-уудын стек. Layer-ийг ойлговол image build хурдтай болж, хэмжээ багасна.

Layer яаж үүсдэг вэ?

Dockerfile-ийн мөр бүр (зааврын мөр) шинэ layer үүсгэдэг. Build хийхэд Docker мөр бүрийг дараалан ажиллуулж, үр дүнг layer болгон хадгална.

dockerfile
FROM node:20-alpine      # Layer 1 — суурь image
WORKDIR /app             # Layer 2 — директор үүсгэх
COPY package*.json ./    # Layer 3 — файл хуулах
RUN npm install          # Layer 4 — dependencies суулгах
COPY . .                 # Layer 5 — код хуулах
CMD ["node", "server.js"]# Metadata (layer биш)

Layer бүр өмнөх layer-ийн дээр хийгдсэн өөрчлөлтийг агуулна — зөвхөн diff.

docker history — layer харах

bash
docker history myapp:1.0
код
IMAGE          CREATED        CREATED BY                                SIZE
3f2a1b4c5d6e   2 minutes ago  CMD ["node" "server.js"]                  0B
8a7b6c5d4e3f   2 minutes ago  COPY . .                                  2.3kB
1e2d3c4b5a6f   3 minutes ago  RUN npm install                           4.2MB
9c8b7a6f5e4d   3 minutes ago  COPY package*.json ./                     1.1kB
2f3e4d5c6b7a   3 minutes ago  WORKDIR /app                              0B
a0f1e2d3c4b5   2 weeks ago    /bin/sh -c #(nop)  CMD ["node"]           0B
...
  • SIZE — Тэр layer-ийн нэмсэн хэмжээ
  • 0B — Файл системд өөрчлөлт оруулаагүй заавар (CMD, EXPOSE, ENV)

Cache яаж ажилладаг вэ?

Docker layer бүрийг кэшэлдэг. Дахин build хийхэд:

  1. Layer-ийн заавар өмнөхтэй ижил → cache ашиглана ⚡
  2. Layer-ийн заавар өөрчлөгдсөн → тэр layer болон бүх дараах layer-ийг дахин build хийнэ
код
Build #1:
  Layer 1 (FROM)     → Build ✓  [кэш үүслээ]
  Layer 2 (WORKDIR)  → Build ✓  [кэш үүслээ]
  Layer 3 (COPY pkg) → Build ✓  [кэш үүслээ]
  Layer 4 (npm i)    → Build ✓  [кэш үүслээ]
  Layer 5 (COPY .)   → Build ✓  [кэш үүслээ]

Build #2 (зөвхөн server.js өөрчлөгдсөн):
  Layer 1 (FROM)     → Cache ✓ ⚡
  Layer 2 (WORKDIR)  → Cache ✓ ⚡
  Layer 3 (COPY pkg) → Cache ✓ ⚡ (package.json өөрчлөгдөөгүй)
  Layer 4 (npm i)    → Cache ✓ ⚡ (package.json өөрчлөгдөөгүй)
  Layer 5 (COPY .)   → Build ✓  (server.js өөрчлөгдсөн!)

Build #2 нь Layer 5-ийг л дахин build хийсэн — маш хурдан.

Cache invalidation

Layer өөрчлөгдсөн гэж үзэх нөхцөлүүд:

COPY/ADD заавар: Файлын агуулга өөрчлөгдсөн бол cache хүчингүй болно.

RUN заавар: Командын текст өөрчлөгдсөн бол cache хүчингүй болно. Гадаад нөөц (npm registry, apt server) өөрчлөгдсөн ч Docker мэдэхгүй — командын текст ижил бол cache ашиглана.

dockerfile
# Энэ cache хэзээ ч шинэчлэгдэхгүй болж магадгүй
RUN apt update && apt install -y curl

Шинэ package татахыг баталгаажуулахад --no-cache флаг:

bash
docker build --no-cache -t myapp .

Layer-ийг оновчтой зохион байгуулах

Бага өөрчлөгддөг зүйлс дээр, их өөрчлөгддөг зүйлс доор

dockerfile
# ❌ Муу — код өөрчлөгдөх бүрт npm install давтагдана
FROM node:20-alpine
WORKDIR /app
COPY . .              # Код + package.json хамт хуулна
RUN npm install       # Бүх удаа дахин суулгана
CMD ["node", "server.js"]
dockerfile
# ✅ Сайн — package.json өөрчлөгдөөгүй бол npm install cache-аас
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./ # Эхлээд зөвхөн package файлууд
RUN npm install        # Package өөрчлөгдөөгүй бол cache ✓
COPY . .               # Дараа нь код (их өөрчлөгддөг)
CMD ["node", "server.js"]

RUN командуудыг нэгтгэх

dockerfile
# ❌ Муу — 4 давхарга, дискний зай их
RUN apt update
RUN apt install -y curl
RUN apt install -y git
RUN apt clean

# ✅ Сайн — 1 давхарга
RUN apt update \
    && apt install -y curl git \
    && apt clean \
    && rm -rf /var/lib/apt/lists/*

rm -rf /var/lib/apt/lists/* — apt cache устгах нь layer-ийн хэмжээг багасгана.

Python жишээ

dockerfile
FROM python:3.12-slim
WORKDIR /app

# ✅ requirements.txt эхлээд — pip install cache ашиглана
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "app.py"]

Layer хуваалцах

Нэг суурь image ашигладаг хэд хэдэн image нэг layer хуваалцана:

код
myapp-v1   myapp-v2   myapp-v3
    \          |          /
     \         |         /
      node:20-alpine (Layer 1)

node:20-alpine layer disk дээр нэг удаа хадгалагдана. Энэ нь:

  • Disk хэмжэглэх зай хэмнэнэ
  • Pull/push хурдасна

Cache оновчтой ашиглах зөвлөмжүүд

1. Нийтлэг зааврыг дээр байрлуул:

dockerfile
FROM node:20-alpine
RUN apk add --no-cache git  # Ховор өөрчлөгддөг → дээр
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .

2. ARG ашиглан cache бүрэн дахин build хийх:

dockerfile
ARG CACHE_BUST=1
RUN apt update && apt install -y curl  # CACHE_BUST өөрчлөгдвөл дахин build
bash
docker build --build-arg CACHE_BUST=$(date +%s) -t myapp .

3. docker system df — disk ашиглалт:

bash
docker system df
код
TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
Images          12      3       2.1GB     1.8GB (85%)
Containers      5       2       145MB     89MB (61%)
Local Volumes   3       2       512MB     0B
Build Cache     28              890MB     890MB

Build cache цэвэрлэх:

bash
docker builder prune

Дараагийн хичээлд:

docker build командыг нарийвчлан үзэж, image-ийг tag хийх, build context, .dockerignore зэргийг судална.