Что такое Dockerfile и как его писать?

Ответ

Dockerfile — это текстовый файл с инструкциями для сборки Docker-образа. Он описывает базовый образ, устанавливает зависимости, копирует код и определяет команды для запуска приложения.

Пример Dockerfile для Spring Boot приложения:

# Многоэтапная сборка для уменьшения размера финального образа
FROM openjdk:17-jdk-slim AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests

# Финальный образ
FROM openjdk:17-jdk-slim
WORKDIR /app
# Копируем только JAR-файл из стадии builder
COPY --from=builder /app/target/myapp.jar app.jar
EXPOSE 8080
# Используем ENTRYPOINT для основной команды, CMD для аргументов по умолчанию
ENTRYPOINT ["java", "-jar", "app.jar"]

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

  1. Многоэтапная сборка — уменьшает размер образа, исключая инструменты сборки.
  2. Оптимизация слоев — копирование зависимостей и исходного кода отдельно для кэширования.
  3. Использование .dockerignore — исключение ненужных файлов (например, target/, .git/).
  4. Минимальные базовые образы (например, -slim, alpine) для безопасности и размера.
  5. Оркестрация — использование docker-compose.yml для запуска нескольких сервисов (приложение + БД + кэш).

Ответ 18+ 🔞

Смотри, вот эта вся история с Dockerfile — она, конечно, гениальная, но иногда такая забористая, что хочется головой об стенку. Представь себе, что это такая кулинарная инструкция для особо одарённого повара-робота. Написал рецепт — он тебе слепил готовый контейнер, банку с приложением, которую можно таскать куда угодно. Красота, да? А на деле — сплошные подводные ебеня.

Вот смотри на этот пример, будто мы Spring Boot приложение упаковываем. Тут главный фокус — не наделать образ на полгигабайта, в котором кроме нашего jar-ника будет ещё пол-интернета мусора.

# Первая стадия — строитель. Тут мы всё собираем.
FROM openjdk:17-jdk-slim AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests

# Вторая стадия — финальная, только для бега.
FROM openjdk:17-jdk-slim
WORKDIR /app
# Хитрая магия: тащим только готовый jar из первой стадии
COPY --from=builder /app/target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Видишь финт? Это многоэтапная сборка. Сначала мы в одном образе (builder) с Maven, всеми зависимостями — этот уёбищный этап, где качается овердохуища всего. А потом берём только результат — jar-файл — и кладём его в чистенький, тощий образ с голой JVM. Весь строительный мусор остаётся за бортом. Итоговый образ легче в разы, а безопасности больше — там меньше всякой дряни, в которую можно тыкать.

А теперь, блядь, главные правила, без которых ты накосячишь так, что потом месяц разгребать:

  1. Слои — они как луковица, их нужно кэшировать. Располагай инструкции в Dockerfile от реже меняющихся к чаще меняющимся. Сначала COPY pom.xml ., потом RUN mvn dependency:go-offline, а уж потом COPY src ./src. Так при изменении только кода не будет каждый раз интернет дохуя качать.
  2. .dockerignore — это святое. Создай этот файл и напиши туда target/, .git/, *.iml, .DS_Store. Иначе твой образ будет весить как чугунный мост, потому что в него попадёт всякий хлам, который Maven или IDE нагенерили. Это просто пиздец как важно.
  3. Не бери образы-переростки. openjdk:17 — это жирно. openjdk:17-jdk-slim или, если очень хочется экстрима, openjdk:17-alpine — уже лучше. Меньше поверхности для атаки, меньше места.
  4. Для сложных сценариев — docker-compose.yml. Это когда твоё приложение — не остров, а ему ещё база данных нужна, и Redis, и чёрт в ступе. Ты описываешь весь этот зоопарк в одном файле, и одной командой docker-compose up всё поднимается. Идеально для локальной разработки, ёпта.

Короче, смысл в чём: Docker — это мощно, но если делать на отъебись, получится медленная, дырявая и жирная хуйня. Потрать время на написание грамотного Dockerfile — сэкономишь кучу нервов, трафика и дискового пространства. Проверено, блядь.