← Назад к вопросам
Как хранится приложение в Docker image
2.0 Middle🔥 211 комментариев
#Docker, Kubernetes и DevOps#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как хранится приложение в Docker image
Docker image состоит из слоёв (layers), каждый слой представляет собой инкрементальные изменения файловой системы.
1. Слои (Layers) в Docker image
Kаждая строка в Dockerfile создаёт новый слой:
FROM openjdk:17-slim # слой 1 — базовый image
WORKDIR /app # слой 2 — установка рабочей директории
COPY pom.xml . # слой 3 — копирование файлов
RUN mvn clean install -DskipTests # слой 4 — установка зависимостей
COPY src ./src # слой 5 — копирование исходного кода
RUN mvn package # слой 6 — компиляция приложения
EXPOSE 8080 # слой 7 — metadata
ENTRYPOINT ["java", "-jar", "target/app.jar"]
Визуально:
┌─────────────────────────────────────┐
│ Слой 7: ENTRYPOINT metadata │ ← writable layer (во время запуска)
├─────────────────────────────────────┤
│ Слой 6: /target/app.jar (6 MB) │ ← read-only
├─────────────────────────────────────┤
│ Слой 5: /app/src (200 MB) │ ← read-only
├─────────────────────────────────────┤
│ Слой 4: ~/.m2 (dependencies 500 MB) │ ← read-only
├─────────────────────────────────────┤
│ Слой 3: pom.xml (2 KB) │ ← read-only
├─────────────────────────────────────┤
│ Слой 2: /app directory │ ← read-only
├─────────────────────────────────────┤
│ Слой 1: openjdk:17-slim base (500 MB) │ ← read-only
└─────────────────────────────────────┘
2. Union File System (UnionFS)
Docker использует Union File System для объединения слоёв:
# Файлы видны как единая файловая система
docker run -it myapp:latest ls -la /app
# На самом деле:
# /app — виртуальное объединение слоёв
# /app/pom.xml — из слоя 3
# /app/src — из слоя 5
# /app/target — из слоя 6
3. Copy-on-Write (CoW)
Если контейнер изменяет файл из read-only слоя, создаётся копия:
# container layer (writable, создаётся при docker run)
┌───────────────────────────────────┐
│ пользовательские изменения │ ← новый файл
├───────────────────────────────────┤
│ /tmp/logs (контейнер пишет) │ ← CoW копия
├───────────────────────────────────┤
│ read-only слои из image │
└───────────────────────────────────┘
// Если приложение пишет в лог
public class App {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("/tmp/app.log");
fw.write("Hello"); // Docker создаёт CoW копию файла
fw.close();
}
}
4. Размер и кэширование слоёв
# Проверить слои image
$ docker history myapp:latest
IMAGE CREATED CREATED BY SIZE
<image-id> 2 hours ago /bin/sh -c #(nop) ENTRYPOINT ["java" "-jar"… 0B
<image-id> 2 hours ago /bin/sh -c mvn package 200MB
<image-id> 2 hours ago /bin/sh -c mvn clean install -DskipTests 500MB
<image-id> 2 hours ago /bin/sh -c #(nop) COPY file:pom.xml /app 2KB
<image-id> 2 weeks ago /bin/sh -c #(nop) WORKDIR /app 0B
<image-id> 2 weeks ago /bin/sh -c #(nop) FROM openjdk:17-slim:… 500MB
# Общий размер: ~1.2 GB (слои)
5. Слои кэшируются при сборке
# Dockerfile
FROM openjdk:17-slim # слой 1 (кэш из registry)
WORKDIR /app # слой 2 (новый)
COPY pom.xml . # слой 3 (новый)
RUN mvn clean install -DskipTests # слой 4 (кэш, если pom.xml не изменился)
COPY src ./src # слой 5 (новый, исходный код изменился)
RUN mvn package # слой 6 (пересчитывается, т.к. src новый)
При docker build:
- Прочитай pom.xml
- Проверь кэш — есть ли слой с этим pom.xml?
- Если да — используй кэш (быстро)
- Если нет — выполни RUN (медленно)
6. Оптимизация Dockerfile для слоёв
❌ Плохо — изменяет много слоёв:
FROM openjdk:17-slim
WORKDIR /app
COPY . . # копирует всё
RUN mvn clean install && mvn package && rm -rf /tmp/*
✅ Хорошо — оптимизирует слои:
FROM openjdk:17-slim
WORKDIR /app
# слой 1: зависимости (кэшируется хорошо)
COPY pom.xml .
RUN mvn dependency:resolve
# слой 2: код (меняется часто)
COPY src ./src
RUN mvn package -DskipTests
# слой 3: финальный (минимальный)
FROM openjdk:17-slim
COPY --from=0 /app/target/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Multi-stage build (рекомендуется):
# Stage 1: builder
FROM openjdk:17-slim as builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:resolve
COPY src ./src
RUN mvn package -DskipTests
# Stage 2: runtime (маленький образ)
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /build/target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
7. Где хранятся слои на диске
# В Docker daemon
/var/lib/docker/
├── image/
│ └── overlay2/
│ └── layerdb/
│ └── sha256/ # индексы слоёв по hash
├── overlay2/ # файловая система слоёв
│ ├── a3b2c1d4.../
│ │ ├── diff/ # изменения в этом слое
│ │ ├── work/ # рабочая директория
│ │ └── merged/ # объединённая FS
│ ├── b4c3d2e5.../
│ └── ...
└── containers/
└── <container-id>/
├── layer/
└── ...
8. Docker image в registry
# Когда пушишь image в Docker Hub
$ docker push myrepo/myapp:1.0
# Docker разделяет на слои
Digest: sha256:abc123... # hash всего image
Config: sha256:def456... # metadata
Layers:
- sha256:layer1... (500 MB) — base image
- sha256:layer2... (200 KB) — dependencies
- sha256:layer3... (150 MB) — code
- sha256:layer4... (10 MB) — binary
# При pull загружаются только новые слои
9. Размер контейнера vs image
# Image size (read-only слои)
$ docker images
REPOSITORY TAG SIZE
myapp latest 706MB
# Размер контейнера при запуске
$ docker ps -s
CONTAINER ID SIZE
abc123... 50MB # 50 MB новых файлов (CoW слой)
# Общее:
# - image: 706 MB (на диске, кэшируется)
# - контейнер: 706 + 50 = 756 MB (при запуске)
10. Inspect layers
# Посмотреть конфиг image
$ docker inspect myapp:latest
[
{
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:abc123...", # слой 1
"sha256:def456...", # слой 2
"sha256:ghi789..." # слой 3
]
}
}
]
# Или через dive (инструмент для анализа)
$ dive myapp:latest
Итого
- Docker image = стек read-only слоёв + metadata
- Каждая команда Dockerfile = новый слой
- Union File System объединяет слои в один
- Copy-on-Write позволяет контейнеру менять файлы
- Кэширование слоёв ускоряет сборку
- Multi-stage builds уменьшают размер итогового image
- При docker push слои отправляются отдельно (экономия трафика)