Статьи

Запускать тесты Java EE в Docker с использованием Arquillian Cube

Технический совет № 61 показал, как запустить практическую лабораторию Java EE 7 с помощью Docker. Используемый там Dockerfile можно использовать для создания нового образа, который может развернуть любой WAR-файл Java EE 7 в экземпляре WildFly, запущенном в контейнере.

Например, github.com/arun-gupta/docker-images/blob/master/javaee7-test/Dockerfile можно скопировать в корневой каталог javaee7-samples и использовать для развертывания jaxrs-client.war в контейнере. Конечно, сначала вам нужно построить образец как:

1
mvn -f jaxrs/jaxrs-client/pom.xml clean package -DskipTests

Точный Dockerfile показан здесь:

1
2
FROM arungupta/wildfly-centos
ADD jaxrs/jaxrs-client/target/jaxrs-client.war /opt/wildfly/standalone/deployments/

Если вы хотите развернуть другое приложение Java EE 7, вам необходимо выполнить следующие шаги:

  • Создайте файл WAR образца
  • Изменить Dockerfile
  • Постройте изображение
  • Остановить предыдущий контейнер
  • Запустить новый контейнер

Теперь, если вы хотите запустить тесты для этого экземпляра, тогда mvn test себе этого не сделает, потому что вам нужно либо статически связать IP-адрес контейнера Docker, либо динамически определить адрес, а затем исправить его во время выполнения. Во всяком случае, повторный цикл немного слишком громоздок. Как вы это решаете?

Познакомьтесь с Arquillian Cube !

Arquillian Cube позволяет вам контролировать жизненный цикл образов Docker как часть жизненного цикла теста, автоматически или вручную.

Запись в блоге содержит более подробную информацию о начале работы с Arquillian Cube, и теперь эта функция включена в ветке «docker» javaee7-samples . Расширение Arquillian Cube Alpha2 было недавно выпущено и используется для обеспечения интеграции. Вот ключевые понятия:

  • Вводится новый профиль «wildfly-docker-arquillian»
  • Профиль добавляет зависимость от:
    1
    2
    3
    4
    5
    6
    <dependency>
        <groupId>org.arquillian.cube</groupId>
        <artifactId>arquillian-cube-docker</artifactId>
        <version>1.0.0.Alpha2</version>
        <scope>test</scope>
    </dependency>
  • Использует Docker REST API для связи с контейнером. Полные документы API показывают примеры полезных нагрузок и объясняют параметры запроса и коды состояния.
  • Использует удаленный адаптер WildFly для связи с сервером приложений, работающим в контейнере
  • Конфигурация образа Docker указана как часть maven-surefire-plugin .:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <configuration>
        <systemPropertyVariables>
        <arquillian.launch>wildfly-docker</arquillian.launch>
        <arq.container.wildfly-docker.configuration.username>admin</arq.container.wildfly-docker.configuration.username>
        <arq.container.wildfly-docker.configuration.password>Admin#70365</arq.container.wildfly-docker.configuration.password>
        <arq.extension.docker.serverVersion>1.15</arq.extension.docker.serverVersion>
        <arq.extension.docker.serverUri>http://127.0.0.1:2375</arq.extension.docker.serverUri>
        <arq.extension.docker.dockerContainers>
            wildfly-docker:
                image: arungupta/javaee7-samples-wildfly
                exposedPorts: [8080/tcp, 9990/tcp]
                await:
                    strategy: polling
                    sleepPollingTime: 50000
                    iterations: 5
                portBindings: [8080/tcp, 9990/tcp]
        </arq.extension.docker.dockerContainers>
        </systemPropertyVariables>
    </configuration>

    Имя пользователя и пароль указаны для WildFly на изображении arungupta / javaee7-samples-wildfly . Все значения конфигурации могут быть переопределены файлом arquillian.xml для каждого теста, как описано здесь .

Как вы опробуете эту функциональность?

1
2
3
git clone https://github.com/javaee-samples/javaee7-samples.git
git checkout docker
mvn test -f servlet/simple-servlet/pom.xml -Pwildfly-docker-arquillian

Вот полный журнал выполнения теста простого сервлета :

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
Running org.javaee7.servlet.metadata.complete.SimpleServletTest
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.
Dec 04, 2014 11:19:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Sending client request on thread main
1 > GET http://127.0.0.1:2375/v1.15/_ping
  
Dec 04, 2014 11:19:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * Client response received on thread main
2 < 200
2 < Content-Length: 2
2 < Content-Type: application/json; charset=utf-8
2 < Date: Thu, 04 Dec 2014 19:19:51 GMT
OK
  
Dec 04, 2014 11:19:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 3 * Sending client request on thread main
3 > POST http://127.0.0.1:2375/v1.15/containers/create?name=wildfly-docker
3 > Accept: application/json
3 > Content-Type: application/json
{"name":"wildfly-docker","Hostname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Dns":null,"Image":"arungupta/javaee7-samples-wildfly","Volumes":{},"VolumesFrom":[],"WorkingDir":"","DisableNetwork":false,"ExposedPorts":{"8080/tcp":{},"9990/tcp":{}}}
  
Dec 04, 2014 11:19:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 4 * Client response received on thread main
4 < 201
4 < Content-Length: 90
4 < Content-Type: application/json
4 < Date: Thu, 04 Dec 2014 19:19:51 GMT
{"Id":"d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b","Warnings":null}
  
  
Dec 04, 2014 11:19:51 AM org.arquillian.cube.impl.docker.DockerClientExecutor assignPorts
INFO: Only exposed port is set and it will be used as port binding as well. 8080/tcp
Dec 04, 2014 11:19:51 AM org.arquillian.cube.impl.docker.DockerClientExecutor assignPorts
INFO: Only exposed port is set and it will be used as port binding as well. 9990/tcp
Dec 04, 2014 11:19:52 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 5 * Sending client request on thread main
5 > POST http://127.0.0.1:2375/v1.15/containers/wildfly-docker/start
5 > Accept: application/json
5 > Content-Type: application/json
{"containerId":"wildfly-docker","Binds":[],"Links":[],"LxcConf":null,"PortBindings":{"8080/tcp":[{"HostIp":"","HostPort":"8080"}],"9990/tcp":[{"HostIp":"","HostPort":"9990"}]},"PublishAllPorts":false,"Privileged":false,"Dns":null,"DnsSearch":null,"VolumesFrom":null,"NetworkMode":"bridge","Devices":null,"RestartPolicy":null,"CapAdd":null,"CapDrop":null}
  
Dec 04, 2014 11:19:52 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 6 * Client response received on thread main
6 < 204
6 < Date: Thu, 04 Dec 2014 19:19:52 GMT
  
Dec 04, 2014 11:19:52 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 7 * Sending client request on thread main
7 > GET http://127.0.0.1:2375/v1.15/containers/wildfly-docker/json
7 > Accept: application/json
  
Dec 04, 2014 11:19:52 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 8 * Client response received on thread main
8 < 200
8 < Content-Type: application/json
8 < Date: Thu, 04 Dec 2014 19:19:52 GMT
8 < Transfer-Encoding: chunked
{"Args":["-b","0.0.0.0","-bmanagement","0.0.0.0"],"Config":{"AttachStderr":false,"AttachStdin":false,"AttachStdout":false,"Cmd":["/opt/wildfly/bin/standalone.sh","-b","0.0.0.0","-bmanagement","0.0.0.0"],"CpuShares":0,"Cpuset":"","Domainname":"","Entrypoint":null,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","WILDFLY_VERSION=8.1.0.Final","JBOSS_HOME=/opt/wildfly"],"ExposedPorts":{"8080/tcp":{},"9990/tcp":{}},"Hostname":"d2fc85815256","Image":"arungupta/javaee7-samples-wildfly","Memory":0,"MemorySwap":0,"NetworkDisabled":false,"OnBuild":null,"OpenStdin":false,"PortSpecs":null,"SecurityOpt":null,"StdinOnce":false,"Tty":false,"User":"wildfly","Volumes":null,"WorkingDir":""},"Created":"2014-12-04T19:19:51.7226858Z","Driver":"devicemapper","ExecDriver":"native-0.2","HostConfig":{"Binds":[],"CapAdd":null,"CapDrop":null,"ContainerIDFile":"","Devices":null,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"Links":null,"LxcConf":null,"NetworkMode":"bridge","PortBindings":{"8080/tcp":[{"HostIp":"","HostPort":"8080"}],"9990/tcp":[{"HostIp":"","HostPort":"9990"}]},"Privileged":false,"PublishAllPorts":false,"RestartPolicy":{"MaximumRetryCount":0,"Name":""},"VolumesFrom":null},"HostnamePath":"/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/hostname","HostsPath":"/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/hosts","Id":"d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b","Image":"3d08e8466496412daadeba7bb35b5b64d29b32adedd64472ad775d6da5011913","MountLabel":"system_u:object_r:svirt_sandbox_file_t:s0:c34,c113","Name":"/wildfly-docker","NetworkSettings":{"Bridge":"docker0","Gateway":"172.17.42.1","IPAddress":"172.17.0.7","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:07","PortMapping":null,"Ports":{"8080/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}],"9990/tcp":[{"HostIp":"0.0.0.0","HostPort":"9990"}]}},"Path":"/opt/wildfly/bin/standalone.sh","ProcessLabel":"system_u:system_r:svirt_lxc_net_t:s0:c34,c113","ResolvConfPath":"/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/resolv.conf","State":{"ExitCode":0,"FinishedAt":"0001-01-01T00:00:00Z","Paused":false,"Pid":11406,"Restarting":false,"Running":true,"StartedAt":"2014-12-04T19:19:52.378418242Z"},"Volumes":{},"VolumesRW":{}}
  
  
Dec 04, 2014 11:20:44 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.0.Beta2
Dec 04, 2014 11:20:44 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.2.0.Beta2
Dec 04, 2014 11:20:44 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version (unknown)
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 65.635 sec - in org.javaee7.servlet.metadata.complete.SimpleServletTest
Dec 04, 2014 11:20:54 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 9 * Sending client request on thread main
9 > POST http://127.0.0.1:2375/v1.15/containers/wildfly-docker/stop?t=10
9 > Accept: application/json
9 > Content-Type: application/json
  
Dec 04, 2014 11:21:04 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 10 * Client response received on thread main
10 < 204
10 < Date: Thu, 04 Dec 2014 19:21:04 GMT
  
Dec 04, 2014 11:21:04 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 11 * Sending client request on thread main
11 > DELETE http://127.0.0.1:2375/v1.15/containers/wildfly-docker?v=0&force=0
11 > Accept: application/json
  
Dec 04, 2014 11:21:05 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 12 * Client response received on thread main
12 < 204
12 < Date: Thu, 04 Dec 2014 19:21:05 GMT
  
  
Results :
  
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
  
[INFO]
[INFO] --- maven-surefire-plugin:2.17:test (spock-test) @ simple-servlet ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:27.831s
[INFO] Finished at: Thu Dec 04 11:21:05 PST 2014
[INFO] Final Memory: 21M/59M
[INFO] ------------------------------------------------------------------------

Полезная нагрузка REST от клиента до сервера Docker показана здесь. Это было проверено на образе Fedora 20 Virtual Box. Вот несколько быстрых заметок по настройке:

  1. Установите необходимые пакеты
    1
    2
    yum install docker-io git maven
    yum upgrade selinux-policy
  2. Настроить Docker
    1
    2
    3
    sudo vi /etc/sysconfig/docker
    Change to "OPTIONS=--selinux-enabled -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"
    sudo service docker start
  3. Проверьте настройку Docker TCP
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    docker -H tcp://127.0.0.1:2375 version
     
    Client version: 1.3.1
    Client API version: 1.15
    Go version (client): go1.3.3
    Git commit (client): 4e9bbfa/1.3.1
    OS/Arch (client): linux/amd64
    Server version: 1.3.1
    Server API version: 1.15
    Go version (server): go1.3.3
    Git commit (server): 4e9bbfa/1.3.1

Boot2docker на Mac по-прежнему имеет проблему № 49, в конце концов , это Alpha2!

Попробуйте другие тесты Java EE 7 и ошибки в файлах здесь .

Наслаждайтесь!