I am trying to dockerize some Tomcat application but I never touch Java application before so the lack of understand it makes it really hard to understand what should I do.
So far I have this but it doesn't work and I don't if it's the correct path as well
FROM tomcat:6
ENV APP_ROOT /app_name
RUN apt-get update && apt-get install -y default-jdk
COPY . $APP_ROOT/
WORKDIR $APP_ROOT
RUN jar -cvf app_name.war *
# this fail for some reason, when I do `ls` the file is there but if fail to copy it
COPY app_name.war $CATALINA_BASE/webapps/app_name.war
I am just going on loop on this because I don't understand and Google Search do not help me that much (I don't know how to ask).
Should I use the jar command in the build? If not, I guess I have to build it locally and just make sure that the .war is there right?!
How the building of the Java with Tomcat app works? and How to integrate with Docker?
Sorry for being too generic but I don't understand anything about Java
Looking at your code this is what I could gleam:
You have some java files stored in current directory (.)
When you call COPY you copy all these contents to /app_name
You create a .war on the file
There are some things to note, first is that the app_name.war is not on the host disk, it is currently inside of the docker file system. What this means is that you cannot COPY the .war.
What you are really after is this: RUN cp app_name.war $CATALINA_BASE/webapps/app_name.war
This would look like the following:
Dockerfile
FROM tomcat:6
ENV APP_ROOT /app_name
RUN apt-get update && apt-get install -y default-jdk
COPY . $APP_ROOT/
WORKDIR $APP_ROOT
RUN jar -cvf app_name.war *
RUN cp app_name.war $CATALINA_BASE/webapps/app_name.war
Adding the docker COPY reference here as it explains the command in detail. It might also be helpful for you to make a script called provision.sh, then do something like:
COPY provision.sh /tmp/provision.sh
RUN sh /tmp/provision.sh
That way you can put all your building, configuring and other in a single script that you can test locally (again if it helps)
EDIT: Adding mention about building locally and copying into dockerfile
You can build the .war on your machine, use COPY to put is on the machine.
Dockerfile
FROM tomcat:6
ENV APP_ROOT /app_name
RUN apt-get update && apt-get install -y default-jdk
COPY app_name.war $CATALINA_BASE/webapps/app_name.war
WORKDIR $APP_ROOT
The above copies the file app_name.war then add it to the filesystem of the container at the path $CATALINA_BASE/webapps/app_name.war. So for that you do this:
Build the .war on your machine with java
Put .war in directory with Dockerfile
COPY app_name.war into the container's filesystem
You can try to do this "by hand" before trying to automate it, it should help to understand the process. You don't need to extend a tomcat official image to be able to deploy a war on a dockerized tomcat, you can use the image directly if you don't need to customize permissions and users (in production, you need).
If you need Tomcat 6.x because your webapp implements servlet API < 3, do this :
sudo docker run --name tomcat --detach --port 8080:8080 tomcat:6
Now, your Tomcat is running in background (--detach), waiting for a deployment. You've exported port 8080 from the container and mapped it to port 8080 from you host, so the app will be available at http://localhost:8080/ on your host.
From now if you copy your .war in /usr/local/tomcat/webapps into the container, the app will be deployed :
sudo docker cp app_name.war tomcat:/usr/local/tomcat/webapps/
I don't use docker, I use a similar AWS product called codedeploy for provisioning instances, so I tell you what I do for Tomcat setup in my provisioning scripts. Should be easy to port to docker as just bash comands.
1) Build the WAR
Most java applications these days are built using Maven but Gradle is catching up. Maven and the WAR plugin are used to turn java code into a WAR file which you can deploy on Tomcat. But it looks like you already have the WAR built by someone else? Either way, you dont run the war directly, you put it in Tomcat, unless you've bundled Tomcat into the app, in which case it would be a JAR but lets not talk about that....The simple solution is build the war from java code using a build tool like Maven or Gradle. By build, I mean turn it from source code to binary.
2) Install Tomcat
yum install tomcat6,7,8 etc etc (Whichever version you need)
Then turn it on
service start tomcat8
3) Deploy the war
To run the war place it in the webapps folder of the Tomcat installation. I generally like to shut tomcat off when I do this but you can do it while its running. After a few seconds the WAR, which is really just a zip file, will be exploded/unzipped to create a directory.
4) Accessing the application/site
If you rename your war to ROOT.war then you can access the applicaition at http://localhost:8080 if your configuration is to have it listen on 8080. If you war is named pets.war then your webapp URL would be http://localhost:8080/pets. You configure which port for Tomcat to listen on in the server.xml file in its conf folder.
Most Important
Tomcat documentation is very good once you know what to look for. The primary configuration files are web.xml, context.xml, and server.xml. The central tomcat guides explain each component https://tomcat.apache.org/tomcat-7.0-doc/setup.html you just need to find the doc that corresponds to your version of Tomcat.
Related
I've got a Springboot jar deployed as a webapp via Docker. Here is the basic outline of my Dockerfile.
#
# Build App
#
FROM maven:3.6.3-openjdk-15-slim AS build
# Copy Parent Project
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package -DskipTests
#
# Deploy App
#
FROM openjdk:15-jdk-alpine
COPY --from=build /home/app/my-app/target/my-app-rest-0.0.1-SNAPSHOT.jar /usr/local/lib/app.jar
ENTRYPOINT exec java -Djava.security.egd=file:/dev/./urandom -jar /usr/local/lib/app.jar
I originally found a pattern similar to this Dockerfile around the internet and I thought I understood most of it, but one thing is eluding me: where are all of the dependency jars that are needed by my app.jar to run? My project is running and executing just fine, so those have to be somewhere in my container. But I've searched and searched but can't find any of the dependency jars or even the WEB-INF directory for my webapp. I know that my actual application jar is in /usr/local/lib/, but that's about all I can deduce.
Is there some default location where the dependency/webapp config would go? Is there something that I can add to my Dockerfile to define where it should go?
Spring boot puts all your dependencies (jars) in fat executable jar, which is the one you are passing to the run stage, and the exact one you are running with the java command.
Since jar files are just compressed archives you can extract them using unzip an peek inside them:
docker cp <container-id>:/home/app/my-app/target/my-app-rest-0.0.1-SNAPSHOT.jar myjar.jar
unzip myjar.jar -d myjar
ls -al myjar/BOOT-INF/lib
And you'll get the list of all the jars you spring boot app depends on.
More information here and here
Maven is used to build your .jar package, while you only need to put the .jar package into docker image and add java -jar ... as the entry point.
Note that Docker is strongly recommending programmers to separate applications into individual docker images. Even if you can have both Maven and .jar together, don't do that.
Is there some default location where the dependency/webapp config would go?
Yes. This is the Dockerfile I use at work. You run maven commands such as clean, package on your development machine, instead of inside a Dockerfile.
FROM openjdk:8-jdk-alpine
# You want to change JDK version.
ADD target/*.jar app.jar
# You have to place this Dockerfile in the SAME directory with the target folder. Then this Dockerfile pulls whatever jar you have under target, renames it to app.jar and adds it to the build.
EXPOSE 9001
# You want to change this to whatever port your java app listens on.
ENTRYPOINT ["java", "-jar", "/app.jar"]
# Typical command you use to run .jar package but this time, you use it as the entrypoint.
As soon as you have that .jar package, cd into the Dockerfile directory and docker build ..
Firstly I am new to docker and most times I see articles on adding jars to docker but my project is modular and below are the list of modules apart from ng client the rest have jar files and the parent package
dao
dao-api
model
ng-client
rest-client
rest-producer
service
service-api
test-db
utility
valen-ezu (this is the parent module cantaining all modules above)
How can put everything in docker correctly and be able to run it rest-producer has a war, not jar, Can I get a step by step approach I am on an ubuntu os I have installed docker and I created a file Dockerfile in the directory of this app
In my Dockerfile I have
FROM openjdk:8
ADD - what next?
I have so many jars and war so can I get an explanation as to how to go about it
If my understanding is correct your build produces a war, that being the case you need an application server. Tomcat could be a good choice, so I would suggest to start by extending your custom image from the official Tomcat Docker image.
Then in your Dockerfile copy the war to the webapps home directory /usr/local/tomcat/webapps/. A basic example:
FROM tomcat
COPY rest-producer.war /usr/local/tomcat/webapps
CMD ["catalina.sh", "run"]
I have a big issue. I'm trying to deploy Spring Boot + Angular 2 web app on heroku but don't know how to do it. I tried several things including:
Making a .war file and deploying it to heroku (source here)
Deploying project as standard java application (source here)
but none of these worked. The first attempt didn't work because I constatly got 404 not found, and the second one didn't work due to, I think, some jar file wasn't found in the location which was described in the Procfile.
Can anyone give me a link, an example, or write a step by step instruction how to achieve this. Thank you.
The most simple way to do it:
run ng build in angular 2 project root (if you are using angular-cli) and copy the content of dist folder to src/main/resources/static/.
create Procfile (for maven):
web: java $JAVA_OPTS -Dserver.port=$PORT -jar target/*.jar
commit and push changes.
Also, you need spring-boot-starter-web present in dependencies. Which has embedded tomcat and automatically configured to serve static content from the static folder.
If you deploy your app as a standard Java application, you can combine it with the Node.js buildpack to run ng build during the Heroku build.
$ heroku buildpacks:add heroku/nodejs
$ heroku buildpacks:add heroku/java
$ git push heroku master
The Node.js buildpack will detect your package.json, install Node.js and run npm. Then the Java build can proceed as normal.
There is a guide for doing something very similar but with Grunt: Using Grunt with Java and Maven to Automate JavaScript Tasks
Use JHipster: https://jhipster.github.io
Once installed, run:
$ yo jhipster
Then run
$ yo jhipster:heroku
Currently, when you deploy a Java WebApp using the default Tomcat, the default Tomcat will listen for WAR archives on D:\home\site\wwwroot\webapps (See https://azure.microsoft.com/en-us/documentation/articles/web-sites-java-add-app/).
The problem is that if you plan to use continuous deployment through GIT, the new fetched archives will be copied under wwwroot folder, not under wwwroot/webapps, so the default Tomcat can listen on them.
Is there any way in which I can tell the default Tomcat to listen for War archives on a specific folder (e.g wwwroot instead) ?
Are there settings that I can play with?
Having a custom Tomcat (second solution of
http://blogs.msdn.com/b/azureossds/archive/2015/12/11/use-custom-context-for-azure-tomcat-application.aspx) is not the most optimal solution, since we will have to copy the Tomcat to all deployment slots that we configure (that's error prone). Deployment slots should be as similar as possible.
At the same time, some of the settings from ApplicationSettings won't be applied anymore, since they apply only on the default Tomcat.
There is my answer for the other thread that the needs was similar with yours. I think it can help you, please refer to the thread Azure Tomcat Eclipse Deployment.
Based on my understanding, you want to deploy the war file into Azure WebApps thru Azure Git continuous deployment. So you can follow the steps modified from the answered thread above, see below.
Open the git bash cmd and make a new directory webapps for war files.
Copy or export the war file into the directory webapps.
git init
git add webapps
git commit -m "Something Commit"
git remote add <app-name> <git-clone-url>
git push <app-name> master
Note: For the variables <app-name> and <git-clone-url>, you can find them on Azure new portal.
Now, you can browse https://<app-name>.azurewebsites.net/<war-file-name> to see it after tomcat unzip the war file to the same name folder automatically.
For continous deployment, you just need to repeat the step 2, 4 and 6.
Any concern, please feel free to let me know.
Does anybody know a gradle 'hot deployment' plugin (or middleware as shell script) which is coping files from source folder directly into project folder at tomcat's webapps directory (not embedded server like gretty or gradle tomcat plugin; version7, environment independent)?
At the end I want to realize a smart dev workflow to (re-, un-) deploy a java web application during code crafting. I'm searching for something like grunt watch tasks.
Scenario: Java web application with self contained, executable jar file at WEB-INF/lib folder.
register watcher tasks on top on gradle task
java source is changed
tomcat stopped
remove jar file at WEB-INF/lib folder
deploy jar file
copy jar into WEB-INF/lib folder
(delete all log files)
start tomcat
Restart tomcat is not needed if static sources are changed (e.g. JSP, JS, ect.).
Solution
I thought about our working practices at the office. My colleagues and I, we program on Windows machines and we use a key map configuration in IDEA to start and stop our local installed Tomcat.
The easiest way for me is to define a user related CATALINA_HOME system environment variable which references the path to Tomcat server.
CATALINA_HOME = C:\Program Files\apache-tomcat-7.0.56
I define a deploy task which copy compiled war file into webapps folder ((re)start Tomcat manually via IEDA).
task deploy(type: Copy) {
def WEBAPPS_HOME = System.getenv()['CATALINA_HOME'] + '/webapps'
from 'build/libs/app.war' into WEBAPPS_HOME
dependsOn war
}
Nobody need to change Tomcat path inside build.gradle file or there is no additional user.config file which is ignored by git.
But I don't like manual Tomcat handling and it is unusual to work with environment variables on Mac's.
So, I decide to search an embedded Tomcat server as Gradle cargo plugin for local development. It is recommanded from Benjamin Muschko (Gradleware Engineer) at How to use local tomcat?... and he describe the differences between Cargo or Tomcat plugin....
Setup of this plugin is quite easy. I don't need to explain.
Nobody need to install there own Tomcat and everybody work with same version server.
For our nigthly build I use the power of Gradle wrapper as Jenkins task configuration.
I execute a wintods batch command.
cd "%WORKSPACE%\app"
gradlew.bat clean build
I use Jenkins to manage deployments for our applications.
There are a number of plugins which help with such tasks along with having the ability to write your own scripts.
Jenkins is highly configurable so you are able to adapt it to your own needs.
Jenkins URL