15 votes

Comment utiliser le volume Docker pour déployer un fichier war / jar dans Tomcat

Est-il possible de déployer un fichier java war ou jar dans Tomcat ? Je recherche de nombreux tutoriels et la seule solution que j'ai trouvée est de copier le fichier war du projet dans /usr/local/tomcat/webapps/.

J'ai utilisé cette solution, mais je voudrais améliorer ma dockerisation. Mon objectif principal est que lorsque je lance mes 2 images (l'application dans tomcat et l'image db) avec docker-compose, je veux utiliser mon fichier war local du dossier cible dans tomcat, et, lorsque je reconstruis le war après un changement de code, ce changement sera reflété sans arrêter les conteneurs, les supprimer et les reconstruire. Pouvez-vous m'aider à faire cela ? Mes tentatives ont échoué. Je veux seulement le faire à des fins de développement.

Voici mon 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"

et le Dockerfile pour ce tomcat

FROM tomcat:8.0-jre8
RUN rm -rvf /usr/local/tomcat/webapps/ROOT
COPY ./docker/app/context.xml /usr/local/tomcat/conf/
# avec la commande de copie suivante ça fonctionne, mais lorsque je reconstruis le fichier war, j'ai besoin d'arrêter docker-compose et le reconstruire et le relancer.. Je veux utiliser un volume au lieu de copier le war
#COPY ./pnp-web/target/pnp.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]

Avec la configuration ci-dessus, l'application démarre, mais lorsque je lance mvn clean package l'application ne se charge plus

ÉDIT

J'ai vérifié le journal du conteneur tomcat et j'ai trouvé cette erreur :

tomcat-cont       | 10 juil. 2018 08:20:36.754 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Déploiement de l'archive de l'application web /usr/local/tomcat/webapps/ROOT.war
tomcat-cont       | 10 juil. 2018 08:20:36.858 GRAVE [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:
tomcat-cont       |  org.apache.catalina.LifecycleException: Échec de démarrage du composant [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
... (remaining content remains the same)

cette erreur s'est produite lorsque j'ai essayé de redémarrer le conteneur lorsque le nouveau war est construit.

12voto

mikaelhg Points 647

Vous avez deux problèmes distincts :

  1. En fonction de la commande que vous utilisez, Maven pourrait bien supprimer et recréer votre répertoire target, ce qui laisserait l'ancien répertoire target supprimé encore ouvert pour le montage de volume par le processus Docker. Votre ancien fichier sera supprimé et le nouveau fichier créé dans un nouveau répertoire dont Docker n'a aucune idée.

  2. Lorsque Maven construit un nouveau fichier WAR ZIP, votre serveur de servlet pourrait remarquer le nouveau fichier en cours de construction et essayer d'ouvrir un WAR à moitié cuit, ce qui se solderait bien sûr par un échec.

Je suggère que vous créiez un répertoire distinct, au moins semi-permanent, en dehors de l'arborescence target, dans le but d'être monté par Docker. Créez un nouveau profil Maven dans votre fichier pom.xml et ajoutez une cible de construction qui copie votre fichier WAR, une fois qu'il a fini d'être construit, dans ce nouveau répertoire que vous montez en tant que webapps de Tomcat à l'intérieur de votre conteneur.

Édition : Voici une solution qui ne dépend pas de la manière particulière dont le système de virtualisation utilisé par Docker pourrait mettre en œuvre le transfert de fichiers de volume sur une plateforme particulière.

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

Extrait de pom.xml :

            org.codehaus.cargo
            cargo-maven2-plugin
            1.6.8

                    tomcat8x
                    remote

                    runtime

                        http
                        localhost
                        8080
                        admin
                        admin

                    remote

                        ${project.groupId}
                        ${project.artifactId}
                        ${project.packaging}

                            /app

Extrait de 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 :

manager-context.xml :

Ensuite :

mvn package

mvn cargo:redeploy

Édition 2 : En réponse à "... est-il possible de le faire sans plugin supplémentaire ?" dans les commentaires :

Oui. Si vous :

  1. Utilisez Windows sur l'hôte et une image Docker Tomcat à l'intérieur d'une machine virtuelle.

  2. Souhaitez accomplir cela en utilisant des volumes et aucun plugin supplémentaire.

... vous pouvez procéder ainsi :

  1. Montez, par exemple, C:/exemple/wars sur /tmp/exemple/wars des conteneurs Docker.

  2. Exécutez mvn package.

  3. Copiez le fichier WAR, par exemple avec un script qui fait tout, de la construction au déploiement, dans le répertoire C:/exemple/wars. Nous ne faisons cette étape que parce que vous pourriez exécuter mvn clean qui supprimera le répertoire target, et si vous l'avez monté directement, Docker pourrait ne pas remarquer le nouveau répertoire target créé par mvn.

  4. Recherchez le nom de votre conteneur avec docker ps.

  5. Exécutez la commande, encore une fois à partir de votre script de déploiement, docker exec $CONTAINER mv /tmp/exemple/wars/*.war /usr/local/tomcat/webapps/ qui copiera, à l'intérieur du conteneur Docker, à l'intérieur de la machine virtuelle, le fichier WAR ZIP complet et non corrompu dans le répertoire de déploiement.

3voto

JoeG Points 1492

Alors que cela NE répond pas exactement à votre question, il existe une alternative à considérer qui ne nécessite pas que vous ayez une configuration de développement différente de celle pour le test ou la production.

Il suffit de construire votre fichier war localement, puis de le docker cp:

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

2voto

Victor Points 1947

Votre problème semble plus simple qu'il n'y paraît. Tout d'abord, oui vous pouvez le faire, un exemple assez bon et de qualité de production ici: https://hub.docker.com/r/esystemstech/liferay

Concernant votre fichier docker, cette ligne ne fait rien pour vous, mis à part masquer les fichiers sous une couche:

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

ce qui signifie que cela ne permet même pas d'économiser de l'espace. Maintenant, envisagez de monter le dossier en tant que volume, au lieu du fichier. Vous pouvez également laisser le contexte à l'intérieur du fichier. et enfin vérifiez simplement si le moment est correct, je veux dire, si vous redémarrez après l'opération de conditionnement. Je dis cela parce que si:

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

D'après ce que je vois dans vos exemples, vous n'avez même pas besoin d'un Dockerfile, vous pouvez remplacer la build par une image dans votre fichier docker-compose, et simplement monter le volume. À moins que vous ne fassiez des choses supplémentaires à l'intérieur du fichier Docker.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X