
Предыдущие части:
Часть 1:
часть 1
Часть 2:
часть 2
Интегрируем Docker в сборку maven-ом
В предыдущей главе мы создали Dockerfile и развернули в нем наш WAR. Это достигалось копированием этого файла из папки
target проекта в папку
docker/deploy и запуском докера из командной строки.
В общем-то, не так уж и сложно, но если вы активно занимаетесь разработкой и и хотите изменить свои исходники и тут же протестировать изменения, то процесс станет утомительным. Теперь, если вы работаете в режиме continuous integration: делаете билд на CI сервере и хотите получить запускаемый образ, надо разобраться, как подружить докер с вашим инструментарием CI.
Давайте рассмотрим более эффективный процесс, в котором мы собираем (и, опционально, запускаем) образ докер в мавене используя плагин Docker.
В интернете вы можете найти несколько плагинов, для рассмотрения в статье я выбрал этот: rhuss/docker-maven-plugin
ссылка. Моя статья не претендует на исчерпывающий разбор и сравнение всех плагинов, поэтому я настоятельно рекомендую изучить сравнение, сделанное Роландом Хуссом: сравнение
сравнение. Этот материал поможет вам выбрать наиболее подходящий плагин для ваших задач.
Мои потребности таковы:
1. Возможность создать образ, базирующийся на образе
Tomcat и содержащий мое приложение.
2. Возможность запустить образ в процессе сборки для моих собственных тестов.
3. Возможность интегрировать образ с фазой сборки maven
test, в которой будут запускаться автоматизированные тесты.
Для этих задач вполне подходит
docker-maven-plugin.
О плагине Maven Docker
Плагин хорошо задокументирован, ноя позволю себе сделать выжимку из документации. Плагин состоит из 2 основных компонентов для конфигурирования:
- Процесс сборки образа и конфигурация запуска задается в pom.xml
- Список файлов для копирования в образ задается в assembly.xml
Настройки для сборки и запуска образа задаются в разделе plugins:
Листинг 8. Конфигурация плагина Docker Maven в POM
<build>
<finalname>helloworld</finalname>
<plugins>
<plugin>
<groupid>org.jolokia</groupid>
<artifactid>docker-maven-plugin</artifactid>
<version>0.13.4</version>
<configuration>
<dockerhost>tcp://192.168.99.100:2376</dockerhost>
<certpath>/Users/shaines/.docker/machine/machines/default</certpath>
<usecolor>true</usecolor>
<images>
<image>
<name>lygado/tomcat-with-my-app:0.1</name>
<alias>tomcat</alias>
<build>
<from>tomcat</from>
<assembly>
<mode>dir</mode>
<basedir>/usr/local/tomcat/webapps</basedir>
<descriptor>assembly.xml</descriptor>
</assembly>
</build>
<run>
<ports>
<port>8080:8080</port>
</ports>
</run>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build> |
<build>
<finalname>helloworld</finalname>
<plugins>
<plugin>
<groupid>org.jolokia</groupid>
<artifactid>docker-maven-plugin</artifactid>
<version>0.13.4</version>
<configuration>
<dockerhost>tcp://192.168.99.100:2376</dockerhost>
<certpath>/Users/shaines/.docker/machine/machines/default</certpath>
<usecolor>true</usecolor>
<images>
<image>
<name>lygado/tomcat-with-my-app:0.1</name>
<alias>tomcat</alias>
<build>
<from>tomcat</from>
<assembly>
<mode>dir</mode>
<basedir>/usr/local/tomcat/webapps</basedir>
<descriptor>assembly.xml</descriptor>
</assembly>
</build>
<run>
<ports>
<port>8080:8080</port>
</ports>
</run>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
Как видим, конфигурация проста и состоит из следующих элементов:
Параметры для идентификации плагина
Строки
groupId,
artifactId, и
version
Глобальная конфигурация
Элементы
dockerHost и
certPath задают ваш докер хост, который назначается при запуске Docker, и путь к сертификату. Путь можно отследить по переменной окружения
DOCKER_CERT_PATH.
Конфигурация образа
Все образы в вашей сборке задаются как дочерние элементы
image в секции
images. Элемент image имеет специфичную структуру, как и секции
build и
run. Специфичным для образа является элемент name. В данном случае это имя образа состоит из имени пользователя (lygado), и имени образа (tomcat-with-my-app), а также версии образа (0.1). В этих секциях вы можете использовать значения
property.
Конфигурация сборки образа
Когда вы собираете образ, как вы ранее делали с помощью команды docker build, вам нужен Dockerfile с описанием действий. Рассматриваемый плагин позволяет использовать докерфайл, но для статьи мы соберем образ по докерфайлу, который создается налету и размещается в памяти. Поэтому мы указываем родительский образ в элементе from – это образ Tomcat.
Плагин maven-assembly-plugin
ссылка определяет общую структуру для включения результатов сборки проекта (зависимостей, модулей, документации для выкладывания в онлайн) в один распространяемый архив, и плагин
docker-maven-plugin придерживается этого стандарта. В нашем примере мы работаем в режиме dir, это означает что файл из
src/main/docker/assembly.xml должны быть скопированы в
basedir нашего образа. Другие режимы — это tar, tgz (GZipped Tar), zip. Элемент
basedir задает папку назначения внутри образа для копирования файлов. В нашем случае это папка
webapps Томката.
Наконец, элемент descriptor сообщает плагину имя файла с инструкциями сборки, он будет в папке
src/main/docker. Наш пример упрощенный, поэтому я рекомендую изучить документацию. В частности, я думаю, что вам будет полезно ознакомиться с элементами:
-
entrypoint и
cmd, которые задают команду для запуска образа
-
env для определения переменных окружения.
-
runCmds для запуска команд как из Dockerfile
-
workdir для смены папки
-
volumes для монтирования
Если кратко: плагин предоставляет все средства для сборки Dockerfile в виде элементов xml.
Конфигурация запуска образа
Когда вы запускаете образ с помощью команды
docker run, вы можете передать параметры. В нашем примере мы запускаем так:
docker run -d -p 8080:8080 lygado/tomcat-with-my-app:0.1 |
docker run -d -p 8080:8080 lygado/tomcat-with-my-app:0.1
Поэтому нужно задать отображение портов.
Элемент
run позволяет параметры запуска, и в нем мы указываем что порт 8080 в контейнере надо прокинуть как порт 8080 на докер хосте. С помощью элемента links можно задать связываемые контейнеры. Команда
docker:start часто используется для запуска интеграционных тестов, поэтому секция run поддерживает элемент
wait для задания паузы. Это время может понадобиться для появления в логе определенной записи или для начала прослушивания определенного URL. Т.е. гарантируется, что образ пришел в рабочее состояние и тесты не завалятся просто из-за поспешного запуска.
Загружаем зависимости
В файле src/main/docker/assembly.xml задаем список файлов для копирования в образ:
Листинг 9. assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<dependencysets>
<dependencyset>
<includes>
<include>com.geekcap.vmturbo:hello-world-servlet-example</include>
</includes>
<outputdirectory>.</outputdirectory>
<outputfilenamemapping>helloworld.war</outputfilenamemapping>
</dependencyset>
</dependencysets>
</assembly> |
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<dependencysets>
<dependencyset>
<includes>
<include>com.geekcap.vmturbo:hello-world-servlet-example</include>
</includes>
<outputdirectory>.</outputdirectory>
<outputfilenamemapping>helloworld.war</outputfilenamemapping>
</dependencyset>
</dependencysets>
</assembly>
В листинге 9 мы видим секцию набора зависимостей, которая включает элемент с нашим артефактом
hello-world-servlet-example, мы хотим увидеть его в . папке. Вспомните, что в POM мы задали
basedir, которая определяла путь к папке
webapps Томката, теперь
outputDirectory указывает путь относительно той базовой папки. Иначе говоря, мы хотим развернуть артефакт
hello-world-servlet-example в папке webapps.
Плагин поддерживает ряд целей (maven target):
docker:build: сборка образа
docker:start: запуск контейнера
docker:stop: остановка контейнера
docker:push: коммит обра в репозиторий, например, в DockerHub
docker:remove: удалить образ с Docker хоста
docker:logs: просмотр логов контейнера
Собираем образ
Вы можете скачать исходники с GitHub
исходники и собрать командой:
Для сборки образа используйте команду:
mvn clean package docker:build |
mvn clean package docker:build
После сборки вы можете убедиться в появлении образа:
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
lygado/tomcat-with-my-app 0.1 1d49e6924d19 16 minutes ago 347.7 MB |
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
lygado/tomcat-with-my-app 0.1 1d49e6924d19 16 minutes ago 347.7 MB
Запускаем контейнер:
Теперь он должен появиться в выводе команды docker ps. Наш сервлет должен прослушивать URL:
http://192.168.99.100:8080/helloworld/hello |
http://192.168.99.100:8080/helloworld/hello
Останавливаем контейнер:
Заключение
Docker – это скорее технология виртуализации на уровне процессов, а не на уровне машин. Docker состоит из клиентского процесса, который взаимодействует с демоном, который запущен на хосте Docker. В linux демон запускается как процесс ОС, в то время как в Windows и Mac он стартует как линуксовая виртуальная машина в VirtualBox и уже в ней работает демон. Образы докера содержат минимальный слой ОС, необходимый для работы, и все бинарники/библиотеки для работы вашего приложения. Образы управляются докерфайлами, в которых содержатся инструкции по конфигурированию.
В этом учебном руководстве я рассказал об азах использования докера, рассмотрел структуру докерфайлов для CentOS, Java, и Tomcat, и показал, как сделать на базе Томката свой образ. В конце статьи мы подключили к нашей сборке плагин docker-maven-plugin. Сделав создание образа и запуск контейнера частью процесса сборки, мы упростили тестирование. Это также позволяет организовать создание образов, готовых для развертывания в продакшн, на CI сервере.