Код
Java
#База знаний

Как работать с Docker: упаковка Spring Boot приложения в контейнер

Немного разбираемся с теорией и проверяем на практике.

 vlada_maestro / shutterstock

Эта статья посвящена основам Docker и раскрывает азы работы с контейнерами. Мы изучим базовые определения и самые необходимые команды и даже разработаем и развернём простейшее Java-приложение.

Что такое Docker

Docker — инструмент, предназначенный для быстрой разработки, доставки и развёртывания приложений. Он позволяет упаковать приложение вместе со всеми его зависимостями в так называемый контейнер, а затем запустить его в любой среде.

Идея контейнеризации состоит в том, что на одной машине может разворачиваться множество таких контейнеров с приложениями. Для каждого из них в операционной системе выделяется изолированная область — осуществляется виртуализация на уровне ОС.

Важный момент: все контейнеры запускаются одинаковым способом вне зависимости от того, что находится внутри. Это напоминает контейнеры для морских перевозок — с виду они одинаковы, но внутри могут храниться совершенно разные грузы.

Преимущества контейнеров:

  • приложения получают единый механизм сборки;
  • не нужно конфигурировать среду для запуска — она поставляется вместе с приложением;
  • приложения легче масштабировать;
  • есть система оркестрации контейнеров, позволяющая ими управлять.

Основные понятия

Образ — некий шаблон, на основе которого создаются контейнеры. Содержит всё необходимое для запуска приложения. Сюда относятся код, системные утилиты, библиотеки, настройки и так далее. Образ можно представить в виде набора слоёв, которые накладываются друг на друга. Каждый последующий добавляет, изменяет или удаляет файлы предыдущего слоя.

DockerfIle — текстовый файл с набором инструкций по созданию образа, каждая из которых добавляет к образу новый слой.

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

Реестр — хранилище образов (как GitHub для кода приложений). Образы можно скачивать из реестра и создавать на их основе контейнеры. Также в реестр можно загружать новые или изменённые образы для дальнейшего использования.

Пример использования

Давайте разработаем простое Spring Boot приложение, создадим на его основе образ и развернём контейнер на локальной машине. Это делается в три простых шага:

  1. Устанавливаем Docker. Все инструкции можно найти на официальном сайте.
  2. Генерируем проект с помощью конструктора Spring. Задаём spring-docker-simple в полях Artifact и Name.
  3. Выбираем одну зависимость — Spring Web. Готово! Скачиваем и распаковываем архив, открываем его в среде разработки.

Код приложения

В открывшемся проекте рядом с главным классом, содержащим метод main, создаём ещё один класс — контроллер с методом hello ().

import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class HelloDockerController {  
  
    @GetMapping("/")  
    public String hello() {  
        return "Hello Docker!";  
    }  
}  

Класс помечен аннотацией @RestController, означающей, что он предназначен для обработки web-запросов. А метод помечен аннотацией @GetMapping c адресом «/» — перейдя по нему (выполнив get-запрос к http://localhost:8080/), мы получим сообщение «Hello Docker!»

Теперь открываем терминал и вводим команду:

./mvnw package && java -jar target/spring-docker-simple-0.0.1-SNAPSHOT.jar 

Она упакует приложение в jar-файл и запустит его. Чтобы убедиться в корректности работы приложения — перейдём на http://localhost:8080/ в браузере и увидим заветное сообщение.

Теперь создаём файл с именем Dockerfile в корне проекта, который содержит инструкции для сборки образа со следующим текстом:

FROM adoptopenjdk/openjdk11:alpine-jre  
ARG JAR_FILE=target/spring-docker-simple-0.0.1-SNAPSHOT.jar  
WORKDIR /opt/app  
COPY ${JAR_FILE} app.jar  
ENTRYPOINT ["java","-jar","app.jar"]  

Вот что происходит, когда мы вводим этот код:

КомандаОписание
FROM adoptopenjdk/openjdk11:alpine-jreOбраз создаётся на основе alpine linux с установленной openjdk11
ARG JAR_FILE=target/spring-docker-simple-0.0.1-SNAPSHOT.jarПеременной JAR_FILE присваивается путь к jar- архиву
WORKDIR /opt/appНазначаем рабочую директорию, в которой будут выполняться дальнейшие команды (перемещаемся в папку app)
COPY ${JAR_FILE} app.jarНаш jar-файл, указанный в JAR_FILE, копируется в папку app, и копии задаётся имя app.jar
ENTRYPOINT [“java","-jar","app.jar"]jar-файл запускается, собирается команда java -jar app.jar из заданной рабочей директории

После этого в терминале вводим команду, с помощью которой собираем образ и запускаем контейнер.

docker build -t spring-docker-simple:0.0.1 .

Точка в конце важна, она указывает на расположение Dockerfile (символ «точка» означает текущую директорию. Проверьте, что образ создан командой docker images. Вывод должен быть таким:

Запускаем контейнер командой:

docker run -d -p 8080:8080 -t spring-docker-simple:0.0.1

Опция -d означает старт процесса в фоновом режиме. Опция -p тоже важна — дело в том, что контейнер собирается в полностью изолированном окружении. Тот факт, что приложение внутри контейнера запущено на порту 8080, не означает, что оно доступно вне контейнера на этом порту.

Требуется явно указать, что порту 8080 в контейнере (здесь второе значение — это порт, на котором работает наше приложение в контейнере) соответствует порт 8080 на локальной машине, который будет использоваться при обращении к контейнеру. Поэтому пишем через двоеточие -p 8080:8080.

Теперь введём в терминале команду:

curl http://localhost:8080 

Так проверяется работоспособность запущенного контейнера. Есть и альтернативный вариант: можно просто перейти по этому адресу в браузере. Если всё работает как надо, задача выполнена — нам удалось упаковать Spring Boot приложение в контейнер.

Частые команды при работе с Docker

docker ps — выводит список запущенных контейнеров. Также ей можно передать параметр -a, чтобы вывести все контейнеры, а не только запущенные.

docker build — собирает образ Docker из Dockerfile и набора файлов, расположенных по определённому пути.

Параметр -t используется, чтобы задать имя образа, последний параметр. — наименование каталога (в нашем случае текущий каталог).

docker images — выводит список образов в вашей системе.

docker logs — позволяет вывести на консоль логи указанного контейнера. Для этого необходимо указать имя или id контейнера. Можно использовать флаг --follow, чтобы следить за логами работающего контейнера: например, docker logs --follow c5ecc88de8f9.

docker run — запускает контейнер на основе указанного образа.

docker stop — останавливает контейнер. Можно передать опцию $(docker ps -a -q) для остановки всех запущенных контейнеров.

docker rm и docker rmi — команды, удаляющие контейнер и образ соответственно.

Удалить все контейнеры:

Заключение

В этом руководстве мы попробовали самостоятельно работать с Docker. Для этого создали простой Spring проект с одной конечной точкой REST и собрали для него образ Docker. В результате научились запускать образ Docker внутри контейнера и протестировали конечную точку REST внутри этого образа.

Docker — удобный инструмент, который значительно ускоряет рабочий процесс. Чтобы узнать о нём больше и получить наиболее полное представление, рекомендую читать официальную документацию.

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Java-разработчик PRO Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована