← Назад к вопросам

Что такое концепция слоев в Docker?

2.0 Middle🔥 141 комментариев
#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое концепция слоев в Docker?

Концепция слоев (Layers) в Docker — это архитектурный принцип, при котором образ (image) состоит из набора стопированных доступных для чтения слоёв файловой системы. Каждый слой содержит изменения по отношению к предыдущему слою, что обеспечивает эффективность и переиспользуемость.

Основные принципы

Структура слоев: Каждый образ Docker построен из слоёв, расположенных друг над другом. При запуске контейнера сверху добавляется тонкий пишущий слой (writable layer), который позволяет контейнеру модифицировать файловую систему.

┌─────────────────────────────┐
│  Container Layer (R/W)      │
├─────────────────────────────┤
│  Layer N (Read-only)        │
├─────────────────────────────┤
│  Layer N-1 (Read-only)      │
├─────────────────────────────┤
│  ...                        │
├─────────────────────────────┤
│  Base Layer (Read-only)     │
└─────────────────────────────┘

Как строятся слои в Dockerfile

Каждая инструкция в Dockerfile потенциально создаёт новый слой:

FROM ubuntu:20.04                    # Слой 1 (базовый образ)
RUN apt-get update                   # Слой 2
RUN apt-get install -y curl          # Слой 3
COPY app.cpp /app/                   # Слой 4
RUN g++ -o /app/app /app/app.cpp     # Слой 5
CMD ["/app/app"]                     # Метаданные (не слой)

Каждый слой содержит только дельту (изменения) по отношению к предыдущему слою.

Union File System (объединённая файловая система)

Docker использует Union File System (например, OverlayFS в Linux) для объединения слоёв в единую файловую систему:

Объединённая FS (видит контейнер):
/usr/bin/curl
/app/app
/etc/config

Фактически состоит из:
Slot 5: /app/app
Slot 4: /app/ (пусто)
Slot 3: /usr/bin/curl
Slot 2: (установленные пакеты)
Slot 1: /ubuntu (базовая система)

Преимущества многослойной архитектуры

1. Эффективность хранения:

Образ A:
- Base Layer (200 MB)
- Dependencies Layer (100 MB)
- App Layer (50 MB)
Всего: 350 MB

Образ B (на основе A):
- Base Layer (переиспользует)
- Dependencies Layer (переиспользует)
- New App Layer (40 MB)
Всего: только 40 MB новых данных!

Благодаря слоям разные образы могут переиспользовать одинаковые слои, экономя место.

2. Быстрое кэширование при сборке:

Докер кэширует каждый слой. Если инструкция не изменилась, слой переиспользуется:

FROM ubuntu:20.04                    # Слой кэшируется
RUN apt-get update && apt-get install -y curl  # Слой кэшируется
COPY app.cpp /app/                   # ПРИ ИЗМЕНЕНИИ — инвалидирует
RUN g++ -o /app/app /app/app.cpp     # ЭТА инструкция пересчитывается

При каждой сборке Docker проверяет:

  • Не изменилась ли инструкция
  • Не изменились ли входные файлы
  • Если всё то же — использует кэш

3. Наслаивание функциональности:

Можно создавать специализированные образы на основе общих:

FROM my-app-base:latest            # Использует готовый слой
RUN apt-get install -y gdb          # Добавляет отладочные инструменты
CMD ["/app/app", "--debug"]         # Переопределяет команду

Оптимизация размера образа

Плохо — много слоёв, большой размер:

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN apt-get install -y git
RUN apt-get install -y gcc

Каждый RUN создаёт слой с промежуточными данными.

Хорошо — объединённые команды:

FROM ubuntu:20.04
RUN apt-get update && \
    apt-get install -y curl wget git gcc && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

Один слой, меньше размер (удалены временные файлы).

Ещё лучше — многошаговая сборка (Multi-stage build):

# Builder stage
FROM ubuntu:20.04 as builder
RUN apt-get update && apt-get install -y g++ cmake
COPY . /src
WORKDIR /src
RUN cmake . && make

# Runtime stage
FROM ubuntu:20.04
COPY --from=builder /src/app /app/app
CMD ["/app/app"]

Второй образ не содержит компилятора и других инструментов разработки.

Слой контейнера (Container Layer)

При запуске контейнера сверху всех слоёв образа добавляется пишущий слой:

// Пример: запуск контейнера
docker run -it myimage

// Внутри контейнера:
echo "new data" > /tmp/file.txt  // Пишется в container layer
cat /app/app.cpp                  // Читается из image layer

Этот слой:

  • Пишется на диск (Copy-on-Write)
  • Специфичен для конкретного контейнера
  • Удаляется при удалении контейнера (если не использовать volume)

Практические команды для работы со слоями

Просмотр слоёв образа:

docker history myimage:latest

Выведет:

IMAGE          CREATED       SIZE      COMMENT
<sha>          2 hours ago   50 MB     RUN g++ ...
<sha>          3 hours ago   100 MB    COPY app.cpp
<sha>          4 hours ago   200 MB    FROM ubuntu:20.04

Инспектирование образа:

docker inspect myimage:latest

Размер образа:

docker images --no-trunc myimage:latest

Применение в Backend-разработке

Оптимальная структура Dockerfile для C++ приложения:

# Builder
FROM gcc:11 as builder
WORKDIR /build
COPY CMakeLists.txt .
COPY src/ src/
RUN apt-get update && apt-get install -y cmake && \
    cmake . && make

# Runtime
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y libssl3 && \
    apt-get clean && rm -rf /var/lib/apt/lists/*
COPY --from=builder /build/app /usr/local/bin/
EXPOSE 8080
CMD ["app"]

Это даёт:

  • Минимальный размер финального образа
  • Отсутствие компилятора в runtime
  • Быстрые пересборки при изменении только кода
  • Хорошую переиспользуемость слоёв между разными приложениями