Как использовать объем докера для развертывания войны/банки в Tomcat

Возможно ли разместить в Tomcat какой-либо файл java war или jar? Я ищу много учебников, и единственным решением, которое я нашел, является копирование файла войны проекта в /usr/local/tomcat/webapps/.

Я действительно использовал это решение, но я хотел бы улучшить свою докерезацию. Моя основная цель - когда я запускаю свои 2 изображения (приложение в tomcat и db-изображении) с помощью docker-compose, я хочу использовать свой локальный файл войны целевой папки в tomcat, и, когда я снова создаю войну после изменения кода, это изменение будут отражаться без остановки контейнеров, их удаления и восстановления. Можете ли вы помочь в этом? Мои попытки не удались. Я хочу это только для цели развития.

Вот мой docker-compose.yml

version: '3'

services:

  tomcat-service:
    build:
      context: ../
      dockerfile: docker/app/Dockerfile
    volumes:
      - D:\myproj\target\app.war:/usr/local/tomcat/webapps/ROOT.war
    ports:
      - "8080:8080"
    depends_on:
      - "db-service"

  db-service:
    build: ./database
    ports:
      - "5433:5432"

и Dockerfile для этого кота

FROM tomcat:8.0-jre8
RUN rm -rvf /usr/local/tomcat/webapps/ROOT
COPY ./docker/app/context.xml /usr/local/tomcat/conf/
# with following copy command it works, but when I rebuild war file, I need stop docker-compose and build and run it again .. I want use volume instead of copy war
#COPY ./pnp-web/target/pnp.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]

С настройкой выше начинается аппликация, но когда я запускаю приложение mvn clean package больше не загружается

РЕДАКТИРОВАТЬ

Я проверил журнал контейнера tomcat и нашел эту ошибку:

tomcat-cont       | 10-Jul-2018 08:20:36.754 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /usr/local/tomcat/webapps/ROOT.war
tomcat-cont       | 10-Jul-2018 08:20:36.858 SEVERE [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
tomcat-cont       |  org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
tomcat-cont       |     at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:755)
tomcat-cont       |     at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:731)
tomcat-cont       |     at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
tomcat-cont       |     at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:973)
tomcat-cont       |     at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1850)
tomcat-cont       |     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
tomcat-cont       |     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
tomcat-cont       |     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
tomcat-cont       |     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
tomcat-cont       |     at java.lang.Thread.run(Thread.java:748)
tomcat-cont       | Caused by: org.apache.catalina.LifecycleException: Failed to start component [[email protected]]
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
tomcat-cont       |     at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:5016)
tomcat-cont       |     at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5149)
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
tomcat-cont       |     ... 10 more
tomcat-cont       | Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [[email protected]]
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:135)
tomcat-cont       |     at org.apache.catalina.webresources.StandardRoot.startInternal(StandardRoot.java:722)
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
tomcat-cont       |     ... 13 more
tomcat-cont       | Caused by: java.lang.IllegalArgumentException: java.util.zip.ZipException: error in opening zip file
tomcat-cont       |     at org.apache.catalina.webresources.AbstractSingleArchiveResourceSet.initInternal(AbstractSingleArchiveResourceSet.java:142)
tomcat-cont       |     at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
tomcat-cont       |     ... 16 more
tomcat-cont       | Caused by: java.util.zip.ZipException: error in opening zip file
tomcat-cont       |     at java.util.zip.ZipFile.open(Native Method)
tomcat-cont       |     at java.util.zip.ZipFile.<init>(ZipFile.java:225)
tomcat-cont       |     at java.util.zip.ZipFile.<init>(ZipFile.java:155)
tomcat-cont       |     at java.util.jar.JarFile.<init>(JarFile.java:166)
tomcat-cont       |     at java.util.jar.JarFile.<init>(JarFile.java:130)
tomcat-cont       |     at org.apache.tomcat.util.compat.JreCompat.jarFileNewInstance(JreCompat.java:170)
tomcat-cont       |     at org.apache.tomcat.util.compat.JreCompat.jarFileNewInstance(JreCompat.java:155)
tomcat-cont       |     at org.apache.catalina.webresources.AbstractSingleArchiveResourceSet.initInternal(AbstractSingleArchiveResourceSet.java:139)
tomcat-cont       |     ... 17 more
tomcat-cont       |
tomcat-cont       | 10-Jul-2018 08:20:36.859 SEVERE [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive /usr/local/tomcat/webapps/ROOT.war
tomcat-cont       |  java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].Stand
ardContext[]]
tomcat-cont       |     at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
tomcat-cont       |     at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:731)
tomcat-cont       |     at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
tomcat-cont       |     at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:973)
tomcat-cont       |     at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1850)
tomcat-cont       |     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
tomcat-cont       |     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
tomcat-cont       |     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
tomcat-cont       |     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
tomcat-cont       |     at java.lang.Thread.run(Thread.java:748)
tomcat-cont       |
tomcat-cont       | 10-Jul-2018 08:20:36.860 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive /usr/local/tomcat/webapps/ROOT.war has finish
ed in 105 ms

эта ошибка произошла, когда я захотел попробовать перезагрузить контейнер при создании новой войны.

Ответы

Ответ 1

У вас есть две отдельные проблемы:

  1. В зависимости от того, какую команду вы используете, Maven вполне может удалить и воссоздать target каталог, который оставит старый, удаленный target каталог, все еще открытый для установки тома, процессом Docker. Ваш старый файл будет удален, а новый файл будет создан в новый каталог, о котором Docker не имеет никакого представления.

  2. Когда Maven строит новый файл WAR WAR, ваш сервлет-бегун может заметить новый файл в середине сборки и попытаться открыть наполовину испеченную WAR, которая, конечно же, закончится сбоем.

Я предлагаю вам создать отдельный, по крайней мере, полупостоянный каталог, а не в target дереве с целью установки Docker. Создайте новый профиль Maven в вашем файле pom.xml и добавьте цель сборки, которая копирует ваш WAR файл после его создания в этот новый каталог, который вы монтируете как Tomcat webapps внутри вашего контейнера.

Edit: Здесь решение, которое не зависит от того, каким образом система виртуализации, используемая Docker, может реализовать передачу файлов томов на любой конкретной платформе.

https://git.mikael.io/mikaelhg/docker-tomcat-war-deploy-poc

pom.xml snippet:

        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <version>1.6.8</version>
            <configuration>
                <container>
                    <containerId>tomcat8x</containerId>
                    <type>remote</type>
                </container>
                <configuration>
                    <type>runtime</type>
                    <properties>
                        <cargo.protocol>http</cargo.protocol>
                        <cargo.hostname>localhost</cargo.hostname>
                        <cargo.servlet.port>8080</cargo.servlet.port>
                        <cargo.remote.username>admin</cargo.remote.username>
                        <cargo.remote.password>admin</cargo.remote.password>
                    </properties>
                </configuration>
                <deployer>
                    <type>remote</type>
                </deployer>
                <deployables>
                    <deployable>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <type>${project.packaging}</type>
                        <properties>
                            <context>/app</context>
                        </properties>
                    </deployable>
                </deployables>
            </configuration>
        </plugin>

docker-compose.yml фрагмент:

tomcat:
  image: tomcat:8
  volumes:
    - ./tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml
    - ./manager-context.xml:/usr/local/tomcat/webapps/manager/META-INF/context.xml
  ports:
    - "8080:8080"
  depends_on:
    - db

tomcat-users.xml:

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
    <role rolename="manager-gui"/>
    <role rolename="manager-script"/>
    <user username="admin" password="admin" roles="manager-gui,manager-script"/>
</tomcat-users>

manager-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true">
    <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

Затем:

mvn package

mvn cargo:redeploy

Редактировать 2: В ответ на "... можно сделать это без дополнительного плагина anz?" в комментариях:

Да. Если ты:

  1. Запускают Windows на хосте и изображение Tomcat Docker внутри виртуальной машины.

  2. Хотите сделать это с помощью томов и дополнительных плагинов.

... вы можете сделать это так:

  1. Подключите, например, C: /example/wars к контейнерам Docker /tmp/example/wars.

  2. Запустите mvn package.

  3. Скопируйте файл WAR, скажем со скриптом, который выполняет все это, от сборки до развертывания, в каталог C: /example/wars. Мы делаем этот шаг только потому, что вы можете запустить mvn clean который удалит target каталог, и если вы подключили его напрямую, Docker может не заметить новый target каталог, созданный mvn.

  4. Посмотрите название своего контейнера с помощью docker ps.

  5. Выполните команду, снова из вашего сценария развертывания, docker exec $CONTAINER mv/tmp/example/wars/*.war/usr/local/tomcat/webapps/ который будет копировать внутри контейнера Docker внутри виртуальной машины, полный, незащищенный WAR файл WAR в каталог развертывания.

Ответ 2

Ваша проблема кажется более простой, чем кажется. Прежде всего, да, вы можете сделать это, довольно хороший и производственный пример: https://hub.docker.com/r/esystemstech/liferay

О вашем файле docker эта строка ничего не делает для вас, кроме скрытия файлов под слоем:

RUN rm -rvf /usr/local/tomcat/webapps/ROOT

что означает, что это даже не экономит место. Теперь рассмотрите возможность установки папки в качестве тома вместо файла. Вы также можете оставить контекст внутри файла. и, наконец, просто проверьте правильность времени, я имею в виду, если вы перезагружаетесь после операции упаковки. Я говорю это, потому что, если:

Caused by: java.util.zip.ZipException: error in opening zip file

Для того, что я вижу в ваших примерах, вам даже не нужен файл Docker, вы можете заменить build image в файле компоновки докеров и просто установить том. Если вы не делаете лишних вещей внутри файла докеров.

Ответ 3

Хотя это НЕ отвечает на ваш вопрос в точности, есть альтернатива для рассмотрения, которая не требует, чтобы у вас была другая конфигурация разработки, чем для тестирования или производства.

Просто создайте свой военный файл локально, а затем docker cp it:

docker cp D:\myproj\target\app.war My_Tomcat_Container:/usr/local/tomcat/webapps/ROOT.war