Docker: docker-maven-plugin – билд Doсker образов в Maven

Автор: | 25/10/2016

docker_lxcdocker-maven-plugin позволяет выполнить сборку Docker образа, включив в него результат билда Maven.

Например – вы собираете веб-приложение в виде war-файла, который потом добавляется в Docker образ с Tomcat, и вы получаете готовое к использованию приложение без необходимости сборки Docker отдельно.

  • Ручная сборка Docker образа с Java приложением
  • Сборка с docker-maven-plugin
  • Push в Docker Hub с docker-maven-plugin

Ручная сборка Docker образа с Java приложением

За пример возьмём Java “Hello, World“:

$ git clone [email protected]:setevoy2/tests.git
Cloning into 'tests'...
remote: Counting objects: 15, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 15 (delta 0), reused 15 (delta 0), pack-reused 0
Receiving objects: 100% (15/15), done.
Checking connectivity... done.

Сначала соберём приложение, Docker-образ, запустим и проверим.

Собираем:

$ cd tests/javahello/
$ ls -l
total 12
-rw-rw-r-- 1 setevoy setevoy  723 жов 20 16:37 pom.xml
drwxrwxr-x 3 setevoy setevoy 4096 жов 20 16:37 src
drwxrwxr-x 4 setevoy setevoy 4096 жов 20 16:37 target
$ mvn clean package
Warning: JAVA_HOME environment variable is not set.
[INFO] Scanning for projects...
...
[INFO] Building war: /home/setevoy/Work/RTFM/tmp/tests/javahello/target/javahello.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.026s
[INFO] Finished at: Thu Oct 20 16:50:26 EEST 2016
[INFO] Final Memory: 9M/236M
[INFO] ----------------------

Проверяем:

$ ls -l target/
total 16
drwxrwxr-x 4 setevoy setevoy 4096 жов 20 16:50 javahello
-rw-rw-r-- 1 setevoy setevoy 2199 жов 20 16:50 javahello.war
drwxrwxr-x 2 setevoy setevoy 4096 жов 20 16:50 maven-archiver
drwxrwxr-x 2 setevoy setevoy 4096 жов 20 16:50 surefire

Проверяем образ Tomcat:

$ sudo docker run -tid dordoka/tomcat
41de280f32a4a27613d556c0c6a1671428b89b5457bf927f053ba7fbbdee8d93
$ sudo docker exec -ti 41de280f32a4a27613d556c0c6a1671428b89b5457bf927f053ba7fbbdee8d93 bash
root@41de280f32a4:/opt/tomcat# ps aux | grep tomcat
root         1 10.1  0.6 7418096 107256 ?      Ssl+ 08:46   0:03 /usr/lib/jvm/java-8-oracle/bin/java -Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/opt/tomcat/endorsed -classpath /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat -Dcatalina.home=/opt/tomcat -Djava.io.tmpdir=/opt/tomcat/temp org.apache.catalina.startup.Bootstrap start
root@41de280f32a4:/opt/tomcat# ls -l webapps/
total 8
drwxr-xr-x 5 root root 4096 Sep 27 08:08 host-manager
drwxr-xr-x 5 root root 4096 Sep 27 08:08 manager

Готовим Dockerfile для сборки образа из Tomcat, в который добавим созданный артефакт:

FROM dordoka/tomcat
COPY target/*.war /opt/tomcat/webapps/
EXPOSE 8080
CMD ["/opt/tomcat/bin/catalina.sh", "run"]

Собираем:

$ sudo docker build -t setevoy/tomcat_hello:2.2 .
Sending build context to Docker daemon 17.41 kB
Sending build context to Docker daemon
Step 0 : FROM dordoka/tomcat
 ---> 1a07d4f8130b
Step 1 : COPY target/javahello.war /opt/tomcat/webapps/
 ---> 466b1ef50d22
Removing intermediate container 362d0b0819fe
Step 2 : EXPOSE 8080
 ---> Running in 1d219440ebb0
 ---> da873ee28eac
Removing intermediate container 1d219440ebb0
Step 3 : CMD /opt/tomcat/bin/catalina.sh run
 ---> Running in e2b76d60f053
 ---> b52ade253209
Removing intermediate container e2b76d60f053
Successfully built b52ade253209

Проверяем:

$ sudo docker run -ti b52ade253209 bash
root@15e58351374c:/opt/tomcat# ls -l webapps/
total 12
drwxr-xr-x 5 root root 4096 Sep 27 08:08 host-manager
-rw-rw-r-- 1 root root 2199 Oct 20 13:50 javahello.war
drwxr-xr-x 5 root root 4096 Sep 27 08:08 manager

Запускаем и получаем IP контейнера:

$ sudo docker run -tid b52ade253209
59da60cdd29dc46641c30b898d61f58a213c740449bf33e7a90fe2650bf334a0
$ sudo docker ps
CONTAINER ID        IMAGE                   COMMAND                CREATED             STATUS              PORTS                NAMES
59da60cdd29d        b52ade253209:latest     "/opt/tomcat/bin/cat   9 seconds ago       Up 8 seconds        8009/tcp, 8080/tcp   boring_payne           
$ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' 59da60cdd29d
172.17.0.59

Проверяем работу приложения:

$ curl 172.17.0.59:8080/javahello/
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

Готово.

Сборка с docker-maven-plugin

Сейчас pom.xml выглядит так

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <groupId>com.setevoy.javahello</groupId>
  <artifactId>javahello</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>javahello Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <dependencies>
  </dependencies>
  
  <build>
    <finalName>javahello</finalName>
  </build>

</project>

Обновляем блок build:

...
  <build>
    <plugins>
      <plugin>
        <groupId>com.spotify</groupId>
        <artifactId>docker-maven-plugin</artifactId>
        <version>0.4.10</version>
        <configuration>
          <dockerDirectory>${project.basedir}</dockerDirectory>
          <imageName>setevoy/${project.artifactId}</imageName>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>build</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
...

Тут мы добавили выполнение build цели плагина docker-maven-plugin (docker:build) во время выполнения фазы package из Maven цикла.

С помощью элемента dockerDirectory мы так же указали искать Dockerfile в корне каталога проекта, и имя образа как setevoy/javahello с помощью переменной project.artifactId.

Собираем:

$ sudo mvn clean package
Warning: JAVA_HOME environment variable is not set.
[INFO] Scanning for projects...
[INFO]
...
[INFO] --- docker-maven-plugin:0.4.10:build (default) @ javahello ---
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[INFO] Copying /home/setevoy/Work/RTFM/tmp/tests/javahello/src/main/webapp/WEB-INF/web.xml -> /home/setevoy/Work/RTFM/tmp/tests/javahello/target/docker/src/main/webapp/WEB-INF/web.xml
...
[INFO] Copying /home/setevoy/Work/RTFM/tmp/tests/javahello/.pom.xml.swp -> /home/setevoy/Work/RTFM/tmp/tests/javahello/target/docker/.pom.xml.swp
[INFO] Building image setevoy/javahello
Step 0 : FROM dordoka/tomcat
 ---> 1a07d4f8130b
Step 1 : COPY target/*.war /opt/tomcat/webapps/
 ---> 28bbe8afcaba
Removing intermediate container 4f36f23af7f3
Step 2 : EXPOSE 8080
 ---> Running in a74ae68dd876
 ---> 43f85a320845
Removing intermediate container a74ae68dd876
Step 3 : CMD /opt/tomcat/bin/catalina.sh run
 ---> Running in b368b7c3f29a
 ---> 17d52f8ceb09
Removing intermediate container b368b7c3f29a
Successfully built 7161e094ece3
[INFO] Built setevoy/javahello
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

Проверяем:

$ sudo docker run -tid 7161e094ece3
a3ad18e8fe311022e718e6907ca20431897eb8393a046cf6e7adb2abff04f14d
$ sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' a3ad18e8fe311022e718e6907ca20431897eb8393a046cf6e7adb2abff04f14d
172.17.0.72
$ curl -L 172.17.0.72:8080/javahello-1.0
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

Push в Docker Hub с docker-maven-plugin

Последним шагом – требуется сохранить собарнный образ в Docker Hub.

В pom.xml, в блоке configurations добавляем:

...
		<serverId>docker-hub</serverId>
		<pushImage>true</pushImage>
...

Приведя его к таком увиду:

...
        <configuration>
          <dockerDirectory>${project.basedir}</dockerDirectory>
          <imageName>setevoy/${project.artifactId}</imageName>
          <serverId>docker-hub</serverId>
          <pushImage>true</pushImage>
        </configuration>
...

Создаём файл maven-settings.xml с параметрами для serverId == docker-hub:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
    https://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>docker-hub</id>
            <username>username</username>
            <password>password</password>
            <configuration>
                <email>[email protected]</email>
            </configuration>
        </server>
    </servers>
</settings>

Собираем:

$ sudo mvn clean package docker:build -s maven-settings.xml
Warning: JAVA_HOME environment variable is not set.
[INFO] Scanning for projects...
...
[INFO] Building image setevoy/javahello
Step 0 : FROM dordoka/tomcat
 ---> 1a07d4f8130b
Step 1 : COPY target/javahello-1.0.war /opt/tomcat/webapps/
 ---> e101dbe5375e
Removing intermediate container 506a452b6fd6
Step 2 : EXPOSE 8080
 ---> Running in 1e7dc21c6e98
 ---> ad0fcf293e96
Removing intermediate container 1e7dc21c6e98
Step 3 : CMD /opt/tomcat/bin/catalina.sh run
 ---> Running in f723508118ac
 ---> d96a1562868d
Removing intermediate container f723508118ac
Successfully built d96a1562868d
[INFO] Built setevoy/javahello
[INFO] Pushing setevoy/javahello
The push refers to a repository [setevoy/javahello] (len: 1)
d96a1562868d: Image already exists 
ad0fcf293e96: Image successfully pushed 
...
Digest: sha256:bbf123c932ddb4b46f758f0d9a931c592017fdaf8b0d75c3aa759184a9c28055
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5:24.729s
[INFO] Finished at: Fri Oct 21 13:21:55 EEST 2016

Проверяем:

$ sudo docker search setevoy/javahello
NAME                DESCRIPTION   STARS     OFFICIAL   AUTOMATED
setevoy/javahello                 0

Готово.

Ссылки по теме:

https://github.com/spotify/docker-maven-plugin

https://www.alooma.com/blog/building-dockers

http://www.disasterarea.co.uk/blog/building-tagging-and-pushing-docker-images-with-maven/