← Назад к вопросам
Какой синтаксис будет у Dockerfile при создании образа проекта?
2.0 Middle🔥 191 комментариев
#Другое
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Dockerfile для Java приложения: синтаксис и лучшие практики
Основная структура Dockerfile
Dockerfile — это файл с инструкциями для построения Docker образа. Для Java приложений структура типична:
FROM openjdk:17-slim
WORKDIR /app
COPY . .
RUN mvn clean package
EXPOSE 8080
CMD ["java", "-jar", "target/app.jar"]
Пошаговый разбор
1. FROM — базовый образ
FROM openjdk:17-slim
- openjdk:17 — образ с установленной Java 17
- slim — облегчённая версия (без ненужных пакетов)
- Альтернативы:
openjdk:21,eclipse-temurin:17,amazoncorretto:17
2. WORKDIR — рабочая директория
WORKDIR /app
- Устанавливает директорию, в которой выполняются команды
- Все последующие операции происходят в
/app - Если директория не существует, Docker создаст её
3. COPY — копирование файлов из хоста
COPY . .
- Первая точка
.— исходная директория на хосте - Вторая точка
.— целевая директория в контейнере (/app) - COPY . . копирует всё содержимое проекта
4. RUN — выполнение команд
RUN mvn clean package
- Выполняет Maven сборку
- Результат:
target/app.jarсоздаётся внутри контейнера - Выполняется во время build, не при запуске контейнера
5. EXPOSE — открытие портов
EXPOSE 8080
- Документирует, какие порты слушает приложение
- Не открывает порты (только информационное)
- Для открытия портов используется флаг
-pприdocker run
6. CMD — команда при запуске контейнера
CMD ["java", "-jar", "target/app.jar"]
- Выполняется при запуске контейнера
- JSON формат:
["исполняемый файл", "аргумент1", "аргумент2"] - Может быть переопределена при
docker run
Полный пример для Spring Boot
# Этап 1: Сборка
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Этап 2: Runtime
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
Multi-stage Dockerfile (лучшая практика)
Много-этапная сборка уменьшает размер итогового образа:
# Этап 1: builder — сборка приложения
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Этап 2: runtime — только нужный JAR
FROM openjdk:17-slim
WORKDIR /app
# Копируем только JAR, без Maven кэша
COPY --from=builder /build/target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Преимущества:
- Образ builder весит ~500MB (с Maven)
- Финальный образ весит ~200MB (только Java + JAR)
- Меньше слоёв и кэша
Инструкции Docker
ENTRYPOINT vs CMD
# CMD — можно переопределить
CMD ["java", "-jar", "app.jar"]
# docker run myimage echo "Hello" # выполнит echo, а не jar
# ENTRYPOINT — основная команда
ENTRYPOINT ["java", "-jar", "app.jar"]
# docker run myimage arg1 arg2 # выполнит: java -jar app.jar arg1 arg2
ENV — переменные окружения
ENV JAVA_OPTS="-Xmx1024m -Xms512m"
ENV SPRING_PROFILES_ACTIVE="production"
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
ARG — аргументы при build
ARG JAVA_VERSION=17
FROM openjdk:${JAVA_VERSION}-slim
ARG APP_VERSION=1.0.0
RUN echo "Building version ${APP_VERSION}"
Использование:
docker build --build-arg JAVA_VERSION=21 .
RUN с несколькими команды
# ❌ Плохо: создаёт несколько слоёв
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
# ✅ Хорошо: один слой
RUN apt-get update && \
apt-get install -y curl && \
apt-get clean
Оптимизированный Dockerfile для Java
# Builder stage
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /src
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests -q
# Runtime stage
FROM openjdk:17-slim
WORKDIR /app
# Не запускать как root
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
# Копируем только JAR
COPY --from=builder --chown=appuser:appuser /src/target/app.jar .
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD java -cp . healthcheck.HealthCheck || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-jar", "app.jar"]
Примеры для разных build систем
Gradle
FROM gradle:7-jdk17 AS builder
WORKDIR /src
COPY build.gradle settings.gradle .
RUN gradle dependencies
COPY src ./src
RUN gradle build -x test
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /src/build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Buildpacks (облегчённый способ)
# Вместо Dockerfile
pack build myapp --builder paketobuildpacks/builder:base
Сборка и запуск
# Сборка образа
docker build -t myapp:1.0 .
docker build -t myapp:latest .
# Запуск контейнера
docker run -p 8080:8080 myapp:1.0
docker run -e SPRING_PROFILES_ACTIVE=prod -p 8080:8080 myapp:1.0
# С переопределением команды
docker run myapp:1.0 java -Xmx2048m -jar app.jar
Лучшие практики
1. Multi-stage сборка
# ✅ Уменьшает размер образа
FROM maven AS builder
RUN mvn package
FROM openjdk:17-slim
COPY --from=builder /app.jar .
2. Кэширование слоёв
# ✅ Зависимости кэшируются
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package
# ❌ Неэффективно
COPY . .
RUN mvn package
3. Минимизация образа
# ✅ slim версия
FROM openjdk:17-slim
# ❌ Полная версия
FROM openjdk:17
4. Контейнерная поддержка памяти
ENTRYPOINT ["java",
"-XX:+UseContainerSupport",
"-XX:MaxRAMPercentage=75.0",
"-jar", "app.jar"]
5. Безопасность
# Не запускать как root
RUN useradd -m appuser
USER appuser
# Только необходимые портов
EXPOSE 8080
.dockerignore — исключение файлов
# .dockerignore
target/
.git/
.gitignore
README.md
*.log
.env
Предотвращает копирование ненужных файлов в образ.
Резюме
Типичный Dockerfile для Java:
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Это многоуровневая сборка, которая:
- Компилирует код в первом образе
- Копирует только JAR во второй образ
- Минимизирует финальный размер образа