W dobie mikroserwisów i CI/CD, rozmiar Twoich obrazów Dockerowych ma znaczenie krytyczne. To nie tylko kwestia miejsca na dysku, ale przede wszystkim szybkości wdrożenia, bezpieczeństwa i kosztów transferu danych.
layers Dlaczego rozmiar ma znaczenie?
Ciężkie obrazy (często przekraczające 1GB dla prostej aplikacji) to zmora każdego DevOpsa. Każdy dodatkowy megabajt to dłuższy czas `docker pull`, większa powierzchnia ataku (dodatkowe pakiety systemowe, których nie potrzebujesz) i wolniejsze skalowanie w sytuacjach awaryjnych.
1. Multi-stage Builds: Święty Graal optymalizacji
To najważniejsza technika, jaką możesz zastosować. Pozwala ona na użycie jednego obrazu do budowania aplikacji (z wszystkimi narzędziami typu compilers, git, npm), a następnie skopiowanie tylko wynikowego pliku binarnego do finalnego, minimalistycznego obrazu.
Przykład: Przed optymalizacją
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
Przykład: Po optymalizacji (Multi-stage)
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm install --production
CMD ["node", "dist/main.js"]
2. Wybór obrazu bazowego: Alpine vs Slim
Zamiast standardowego obrazu `ubuntu` czy `node`, używaj wersji `alpine`. Alpine Linux to dystrybucja o wadze zaledwie ~5MB. Jest bezpieczniejsza, bo zawiera tylko to, co niezbędne. Jeśli Twoja aplikacja wymaga specyficznych bibliotek C, rozważ wersję `-slim`.
3. Potęga .dockerignore
Podobnie jak `.gitignore`, ten plik zapobiega wysyłaniu zbędnych danych do demona Dockera podczas budowania (tzw. build context). Nie kopiuj folderów `node_modules`, `.git`, czy logów. To drastycznie przyspiesza proces `COPY . .`.
4. Łączenie komend w warstwy
Każda instrukcja `RUN`, `COPY`, `ADD` tworzy nową warstwę. Zamiast wielu komend RUN, połącz je w jedną używając `&&` i czyść cache menedżera pakietów w tej samej warstwie.
# Dobra praktyka
RUN apt-get update && apt-get install -y \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
lightbulb Ekspercka rada
Zawsze umieszczaj instrukcje, które zmieniają się najrzadziej (np. instalacja zależności systemowych) na samej górze Dockerfile. Dzięki temu Docker wykorzysta cache przy kolejnych buildach, oszczędzając Twój czas.