Что такое Docker image и как он устроен?

Ответ

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

Ключевые характеристики:

  1. Иммутабельность — образ нельзя изменить после сборки. Любые изменения требуют создания нового образа.
  2. Слоистая структура — каждый шаг в Dockerfile создаёт новый слой. Слои кэшируются и переиспользуются, что ускоряет сборку.
  3. Хранение в реестрах — образы хранятся в реестрах (Docker Hub, AWS ECR, Google Container Registry).

Пример Dockerfile:

# Базовый образ (первый слой)
FROM openjdk:17-jdk-slim

# Установка рабочей директории (второй слой)
WORKDIR /app

# Копирование файлов (третий слой)
COPY target/myapp.jar ./app.jar

# Открытие порта (метаданные, не создаёт слой)
EXPOSE 8080

# Команда запуска (четвёртый слой)
CMD ["java", "-jar", "app.jar"]

Работа с образами:

# Сборка образа из Dockerfile
docker build -t myapp:1.0 .

# Просмотр локальных образов
docker images

# Загрузка образа в реестр
docker push myapp:1.0

# Скачивание образа из реестра
docker pull myapp:1.0

# Удаление локального образа
docker rmi myapp:1.0

Почему слои важны:

  • При изменении одного шага в Dockerfile пересобираются только последующие слои
  • Разные образы могут делиться общими базовыми слоями, экономя дисковое пространство
  • Слоистая структура обеспечивает эффективную дельту при передаче образов

Ответ 18+ 🔞

Давай я тебе про эти ваши докер-образы на пальцах объясню, а то смотрю, народ путается, как хуй с винтом.

Представь себе, что докер-образ — это, блядь, законсервированная банка с борщом, которую твоя бабка закатала на зиму. Всё там есть: и картоха, и свёкла, и мясо, и лаврушка. И главное — эту банку, сука, не переделать. Хочешь меньше соли? Хуй там! Придётся новую банку закатывать, с нуля. Вот и образ — он иммутабельный, то есть неизменяемый, нахуй. Собрал — и ходи, как дурак, с этой банкой.

А внутри этой банки, оказывается, слои, как у матрёшки, блядь. Каждое действие в инструкциях — новый слой. Сначала положили кастрюлю (базовый образ FROM), потом налили воды (WORKDIR), потом накидали овощей (COPY). И если ты, допустим, только специи поменял, то воду и овощи заново тащить не надо — они уже в кэше лежат, ебать мои старые костыли! Умно, да? Экономия времени и места — два в одном, как хуй в пальто.

Хранятся эти банки-образы в специальных кладовках — реестрах. Типа Docker Hub — это такой общий гастроном, куда все носят свои банки. А можно свой погребок завести (AWS ECR или какой-нибудь свой registry).

Смотри, как это выглядит в жизни, на примере простого Dockerfile для Java-приложения:

# Берём готовую банку с Java (базовый образ)
FROM openjdk:17-jdk-slim

# Говорим: "Все следующие ингредиенты — в эту кастрюлю (рабочую директорию)"
WORKDIR /app

# Перекладываем наш готовый борщ (jar-файл) в кастрюлю
COPY target/myapp.jar ./app.jar

# Говорим: "Эту банку можно открыть с одной стороны (порт 8080)"
EXPOSE 8080

# И пишем инструкцию: "Чтобы разогреть, сделай вот так"
CMD ["java", "-jar", "app.jar"]

А вот как этим хозяйством, блядь, управлять через консоль:

# Собрать свою банку с борщом (образ) из рецепта (Dockerfile)
docker build -t myapp:1.0 .

# Посмотреть, какие банки уже стоят у тебя на полке
docker images

# Отнести свою банку в общую кладовку (реестр)
docker push myapp:1.0

# Сходить к соседу и стырить его банку борща (скачать образ)
docker pull myapp:1.0

# Выкинуть просроченную или ненужную банку нахуй
docker rmi myapp:1.0

И главная фишка, на которой все ебут мозг — слои. Они, сука, гениальны.

  • Поменял только последнюю строчку в рецепте? Пересобирается только последний слой, а не вся банка с нуля.
  • У тебя десять разных банок, но все на основе одной и той же картохи? Так картоха-то общая, один слой на всех! Место на диске экономится — овердохуища.
  • Отправляешь обновлённую банку другу? Ему качается только разница между слоями, а не вся хуйня целиком.

Вот и вся магия, ёпта. Не образ, а мечта лентяя-деплоя. Собрал один раз и таскай эту банку куда угодно — везде будет один и тот же борщ. Главное — в рецепте (Dockerfile) не накосячить, а то вместо борща получится какая-то пиздопроебибна, которую и контейнер запустить не захочет.