Зарегистрируйтесь, чтобы продолжить обучение

Docker Java: Продвинутое использование

Команды

docker build . -t my_account_name/awesome-image

Используется для сборки образа. Флаг -t позволяет указать имя образа

docker images

Показывает все собранные образы

docker run -it -p 80:8080 my_account_name/awesome-image

Запускает контейнер. Флаг -p используется для проброса портов: <порт доступный снаружи>:<порт внутри контейнера>

docker push my_account_name/awesome-image

Отправляет образ на dockerhub

docker run -it -p 80:8080 my_account_name/awesome-image bash

А так мы можем запустить образ и подключиться к нему с помощью bash

Dockerfile

# Указываем образ, от которого наследуемся
FROM php:7.4-cli

# Устанавливаем рабочую директорию
WORKDIR /project

# Копируем директорию из основной файловой системы внутрь образа
COPY ./project .

# Определяет действие, которое будет выполнено при старте контейнера (docker run)
# Используется только в случае, если контейнер был запущен без указания команды
# [команда, аргумент]
CMD ["echo", "Hello Hexlet!"]

# Сообщаем, что контейнер использует 8000 порт
EXPOSE 8000

Самостоятельная работа

В этом задании мы познакомимся с Docker и упакуем простое приложение на Spring boot в контейнер.

Установка Docker

  • Установите Docker, следуя инструкции для своей операционной системы

Знакомство с приложением

В репозитории находится очень простое Spring boot приложение. Все, что оно делает – это выводит приветствие при запросе к корневой странице. Приложение стартует на порту 8080

  • Сделайте форк репозитория и склонируйте его на свой компьютер.
  • Изучите код этого приложения, его мы будем упаковывать в контейнер.

Упаковываем приложение в образ

  • Создайте Dockerfile, в него добавим команды для упаковки приложения в образ.

При создании своего образа унаследуйтесть от образа eclipse-temurin:24-jdk. Внутри уже есть установленные jdk24, но нет Gradle. Так как для сборки приложения мы используем Gradle, нужно будет его установить вручную. Как это делается, можно посмотреть в документации. Или просто добавьте код из примера ниже:

Пример команд Dockerfile
# Установим необходимые утилиты и Gradle напрямую
ARG GRADLE_VERSION=8.14
ENV GRADLE_HOME=/opt/gradle
ENV GRADLE_USER_HOME=/gradle-cache
ENV PATH=${GRADLE_HOME}/bin:${PATH}

RUN apt-get update && apt-get install -y curl unzip make && \
  curl -fsSL https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -o gradle.zip && \
  unzip gradle.zip -d /opt && \
  mv /opt/gradle-${GRADLE_VERSION} ${GRADLE_HOME} && \
  rm gradle.zip && \
  gradle --version

WORKDIR /app

# Копируем только файлы, связанные с зависимостями, чтобы кэшировать Gradle
COPY build.gradle* settings.gradle* gradle.properties* Makefile ./

# Создаём пустую структуру src для предварительного запуска
RUN mkdir -p src/main/java

# Прогреваем зависимости (без сборки)
RUN gradle build -x test --dry-run || true

# Копируем остальной проект
COPY . .

# Сборка проекта
RUN make build

EXPOSE 8080

CMD ["make", "run"]

Теперь соберите образ при помощи команды:

  docker build -t <image_name> .

С помощью флага -t передается имя образа, включая имя аккаунта и тег.

После сборки образа вы сможете увидеть его в списке образов. Выполните команду docker images и найдите там свой образ.

Итоговый Dockerfile
FROM eclipse-temurin:24-jdk

# Установим необходимые утилиты и Gradle напрямую
ARG GRADLE_VERSION=8.14
ENV GRADLE_HOME=/opt/gradle
ENV GRADLE_USER_HOME=/gradle-cache
ENV PATH=${GRADLE_HOME}/bin:${PATH}

RUN apt-get update && apt-get install -y curl unzip make && \
  curl -fsSL https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -o gradle.zip && \
  unzip gradle.zip -d /opt && \
  mv /opt/gradle-${GRADLE_VERSION} ${GRADLE_HOME} && \
  rm gradle.zip && \
  gradle --version

WORKDIR /app

# Копируем только файлы, связанные с зависимостями, чтобы кэшировать Gradle
COPY build.gradle* settings.gradle* gradle.properties* Makefile ./

# Создаём пустую структуру src для предварительного запуска
RUN mkdir -p src/main/java

# Прогреваем зависимости (без сборки)
RUN gradle build -x test --dry-run || true

# Копируем остальной проект
COPY . .

# Сборка проекта
RUN make build

EXPOSE 8080

CMD ["make", "run"]

Запуск контейнера с приложением

Так как порт 8080 может быть занят то, а снаружи контейнера приложение будет доступно на порту 3000, нам нужно. Флаг -p сопоставит порт 8080 внутри контейнера с портом 3000 на вашем компьютере. Запустите контейнер при помощи команды:

  docker run -p 3000:8080 --name hello-world-app <image>

Откройте браузер и загрузите страницу http://localhost:3000. Убедитесь, что все работает. Если все сделано верно, вы увидите приветствие.

Остановите образ при помощи комбинации клавиш Ctrl + C. После этого приложение станет недоступно.

После остановки контейнера, он все еще остается. Так как у него есть фиксированное имя, которое задано флагом --name, то Docker не даст запустить контейнер под тем же именем.

Удалите контейнер командой

docker rm hello-world-app

Выполнение команд внутри контейнера

Мы также можем запустить образ и подключиться к нему при помощи команды:

docker run -it -p 3000:8080 <image> bash

Запустится bash сессия внутри контейнера. Изучите файловую систему внутри контейнера. Протестируйте наше приложение, запустите тесты при помощи команды make test. Выйти из контейнера можно при помощи комбинации клавиш Ctrl + D

Make-команды

Добавьте в Makefile команды для работы с контейнером. Вам могут пригодиться следующие команды:

  1. Сборка образа
  2. Запуск приложения
  3. Запуск тестов в контейнере
  4. Запуск сессии bash внутри контейнера
  5. Остановка и удаление образа
Примеры команд для Makefile
docker-build:
  docker build -t java-spring-boot-hello-world .

docker-run:
  docker run -p 3000:8080 --name hello-world-app java-spring-boot-hello-world

docker-bash:
  docker run --rm -it -p 3000:8080 java-spring-boot-hello-world bash

Дополнительное задание

Соберите минимальный Docker-образ для приложения, которое будет выполняться в Production. Он может состоять из нескольких этапов сборки. Для первого этапа вам потребуется базовый образ gradle, а для второго - . Первый образ будет выполнять сборку, а во втором запустится jar.

Пример Dockerfile, который может получиться
# Этап сборки
FROM gradle:8.14-jdk24 AS build
WORKDIR /app
COPY --chown=gradle:gradle . .
RUN gradle build -x test --info --console=plain

# Этап выполнения
FROM eclipse-temurin:24-jre
WORKDIR /app
COPY --from=build /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Подсказки

  • Пример приложения работающего в Docker
  • Не забывайте, что внутри контейнера теперь доступен gradle, который поможет вам собрать и запустить приложение

Дополнительные материалы

  1. Установка Docker
  2. Как и для чего использовать Docker
  3. Введение в Docker

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff