簡體   English   中英

如何使用docker volume在Tomcat中部署war / jar

[英]How to use docker volume to deploy war / jar in Tomcat

是否可以在Tomcat中部署一些java war或jar文件? 我找了很多教程,我找到的唯一解決方案是將項目war文件復制到/usr/local/tomcat/webapps/

我實際上使用了這個解決方案,但我想改進我的dockerisation。 我的主要目標是當我使用docker-compose運行我的2個圖像(tomcat和db image中的應用程序)時,我想在tomcat中使用目標文件夾的本地war文件,當我在代碼更改后再次構建war時,將在不停止容器,移除和重建的情況下進行反映。 你可以幫忙嗎? 我的嘗試失敗了。 我希望它僅用於開發目的。

這是我的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"

和那個tomcat的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 [org.apache.catalina.webresources.StandardRoot@51f50cb1]
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 [org.apache.catalina.webresources.JarResourceSet@20e48a4a]
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目錄,這將使Docker進程仍然為卷裝入打開舊的已刪除target目錄。 您的舊文件將被刪除,新文件將創建到Docker不知道的新目錄中。

  2. 當Maven構建一個新的WAR ZIP文件時,你的servlet運行器可能會注意到中間構建的新文件,並嘗試打開一個半生不熟的WAR,這當然會以失敗告終。

我建議您創建一個單獨的,至少是半永久性的目錄,而不是在target樹中,以便由Docker掛載。 pom.xml文件中創建一個新的Maven配置文件,並添加一個構建目標,在構建完成后將其復制到新目錄中,該目錄將作為Tomcat的webapps掛載到容器中。

編輯:這是一個解決方案,它不依賴於Docker使用的虛擬化系統在任何特定平台上實現卷文件傳輸的特定方式。

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

pom.xml片段:

        <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:作為回應“......如果沒有額外的插件可以做到這一點嗎?” 在評論中:

是。 如果你:

  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可能不會注意到mvn創建的新target目錄。

  4. 使用docker ps查找容器名稱。

  5. 再次從您的部署腳本, docker exec $CONTAINER mv /tmp/example/wars/*.war /usr/local/tomcat/webapps/運行該命令,它將在Docker容器內復制到虛擬機內部,完成,將未破壞的WAR ZIP文件放入部署目錄。

你的問題似乎比看上去簡單。 首先,是的,你可以做到這一點,這是一個非常好的生產等級示例: 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

對於我在示例中看到的內容,您甚至不需要Dockerfile,可以使用docker compose文件中的image替換build ,然后安裝卷。 除非你在docker文件中做了額外的事情。

雖然這不能完全回答您的問題,但有一種替代方案可以考慮,不需要您具有與測試或生產不同的開發配置。

只需在本地構建你的war文件然后docker cp

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM