Как использовать объем докера для развертывания войны/банки в 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
У вас есть две отдельные проблемы:
-
В зависимости от того, какую команду вы используете, Maven вполне может удалить и воссоздать target
каталог, который оставит старый, удаленный target
каталог, все еще открытый для установки тома, процессом Docker. Ваш старый файл будет удален, а новый файл будет создан в новый каталог, о котором Docker не имеет никакого представления.
-
Когда 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?" в комментариях:
Да. Если ты:
-
Запускают Windows на хосте и изображение Tomcat Docker внутри виртуальной машины.
-
Хотите сделать это с помощью томов и дополнительных плагинов.
... вы можете сделать это так:
-
Подключите, например, C: /example/wars
к контейнерам Docker /tmp/example/wars
.
-
Запустите mvn package
.
-
Скопируйте файл WAR, скажем со скриптом, который выполняет все это, от сборки до развертывания, в каталог C: /example/wars
. Мы делаем этот шаг только потому, что вы можете запустить mvn clean
который удалит target
каталог, и если вы подключили его напрямую, Docker может не заметить новый target
каталог, созданный mvn
.
-
Посмотрите название своего контейнера с помощью docker ps
.
-
Выполните команду, снова из вашего сценария развертывания, 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