I am new to containerizing apps using Docker. I could deploy a container including a war file. The war is basically a JAVA web application/servlet that sends back a video file upon receiving the request from end-user. The app deployment using docker was a success and app works fine. However I have some issues regarding its boot time.
From the moment that I create the container by hitting command docker run -it -d -p 8080:8080 surrogate, it takes about 5-6 minutes for the container to become operational, meaning that the first 5-6 minute of the container lifetime, it is not responding to end-user requests, and after that it works fine. Is there any way to accelerate this boot time?
Dockerfile includes:
FROM tomcat:7.0.72-jre7
ADD surrogate-V1.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
WORKDIR "/usr/local/tomcat/"
RUN wget https://www.dropbox.com/s/1r8awydc05ra8wh/a.mp4?dl=1
RUN cp a.mp4\?dl\=1 lego.mp4
(Posted on behalf of the OP).
First get rid of -d in the "docker run" command to see what is going on in the background. I noticed the war deployment phase is taking so long (around 15-20 minutes!!!)
The reason in my case was that the tomcat version in the Dockerfile was different from the Tomcat version in the environment from which I exported the web application as WAR. (How to check JRE version: in terminal enter: JAVA -version, checking the Tomcat version: from eclipse, when you are exporting, it shows the version).
In my case in Dockerfile, I had :
FROM tomcat:7.0.72-jre7
I changed it to:
FROM tomcat:6.0-jre7
It now takes less than 10 seconds!
In a nutshell, make sure that the Tomcat version and JRE versions in the Dockerfile are the same as the environment from which you exported the Java web application as WAR.
Related
I have an OpenLiberty Server which i developed on Eclipse with maven and microprofile framework. It is now just a Java Application as a .jar file. I can execute it with "java -jar name.jar" from the cmd.
I created a docker container based on OpenJdk image and this is the text of my Dockerfile:
FROM openjdk:12-oracle
COPY projectname.jar /projectname.jar
CMD ["java", "-jar", "projectname.jar"]
and created the Image with:
docker build -t takemealong .
and created the container with:
docker run -p 8080:8080 --name TakeMeAlong_Container takemealong
It works fine and i can reach my index.html, but when i stop the Container, the Webserver keep working in the background, even when i stop the entire docker. I can see it in the task manager with the name: "Vmmem" and the index.html still of course reachable.
How can i make it stop, when i stop the docker container?
Stopping container stops also all processes inside. This is the answer on your question. If you have something still running, it must be started from somewhere else (another container or normal system process).
I'm having issues deploying a Quarkus 1.10 application to Heroku as a Docker image.
The same application, using SpringBoot and a similar Docker Image boots successfully, but somehow Quarkus triggers the infamous R10 Boot Timeout error due to bad bind of $PORT, even when I see that the boot times are really small (2 seconds vs. 4.5 of the SpringBoot version).
If I start the image locally, it works perfectly without issues.
My final Docker Image is like this (omitting the Multi-stage build steps for brevity):
FROM gcr.io/distroless/java:11
ENV QUARKUS_MAILER_FROM=${EMAIL_USERNAME} \
QUARKUS_MAILER_USERNAME=${EMAIL_USERNAME} \
QUARKUS_MAILER_PASSWORD=${EMAIL_PASSWORD}
EXPOSE 8080
COPY --from=backend /usr/src/app/target/*-runner.jar /usr/app/app.jar
COPY --from=backend /usr/src/app/target/lib /usr/app/lib
ENTRYPOINT [ "java", "-jar" ]
CMD ["/usr/app/app.jar", "-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=${PORT}"]
I'm using the commands to deploy the application:
heroku container:push web
heroku container:release web
I don't see where the error is. I've also tried to remove the EXPOSE directive from the Dockerfile but that's not the cause of error.
I've solved the issue, which is really dumb.
Modifying the ENTRYPOINT and the CMD sections of the Dockerfile as follows:
ENTRYPOINT [ "java" ]
CMD ["-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=${PORT}", "-jar", "/usr/app/app.jar"]
it works. The problem is, the system properties have to be passed before the -jar parameter, otherwise Quarkus doesn't pick the right value for ${PORT}
My project is moving from Spring Boot 2.0.4 with Java 8 to Spring Boot 2.1.0 with Java 11. When the application was built with Spring Boot 2.0.4 and Java 8 and run in Docker / Docker Compose, the #PostConstruct-annotated method was called, but after the move to Spring Boot 2.1.0 and Java 11 the #PreDestroy-annotated method is no longer called.
I have tried switching from annotations to implementing InitializingBean and DisposableBean as described here, but the DisposableBean.destroy method is not called.
I have also tried adding a dependency to javax.annotation-api version 1.3.2, with the same result.
How to reproduce:
Create a minimal Spring application with a lifecycle bean:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
#Component
public class Life implements InitializingBean, DisposableBean {
#Override
public void destroy() throws Exception {
System.out.println("--- Life.shutdown");
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.println("--- Life.startup");
}
}
Start the Spring application from the target subfolder:
cd target
java -jar demo-0.0.1-SNAPSHOT.jar
When the application is stopped using Ctrl+C, the DisposableBean.destroy is called.
Return to the parent folder:
cd ..
Start the Spring application using Maven:
mvn spring-boot:run
When the application is stopped using Ctrl+C, the DisposableBean.destroy is called.
Dockerfile:
FROM openjdk:11.0.1-jre-slim
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT java -jar /app.jar
Build, run, and stop Docker image:
docker build -t demo .
docker run -p 8080:8080 demo
docker ps
docker stats 3ca5b804ab13
docker stop 3ca5b804ab13
docker logs 3ca5b804ab13
When the application is stopped using docker stop, the DisposableBean.destroy is not called.
docker-compose.yml:
demo:
image: demo
ports:
- '8080:8080'
Run Docker image using Docker Compose (simulating OpenShift):
docker-compose up
docker-compose down
demo_demo_1 exited with code 137
When the application is stopped using docker-compose down, the DisposableBean.destroy is not called.
I suspect that Docker is trying a SIGTERM before it issues a SIGKILL, because there is a 10-second delay before the container is killed.
There are many places where the setup can go wrong.
First I suggest to identify whether java/spring part have some issues or it a docker/environment related issue. From the question it sounds like its java related, but in reality I suspect its not in java/spring.
So, mvn spring-boot:run works as expected, and I see that you package the spring boot application as jar (app.jar) likely with a spring boot plugin. This is also a place where things potentially can go wrong, because spring boot uses a special classloader to load things in runtime.
So in order to fully eliminate the "java/spring" part navigate to your target directory and run java -jar app.jar (make sure that java 11 is installed on your local machine of course). If it doesn't work - investigate java /spring part, otherwise proceed with docker part.
The chances are that the application will work as expected.
Now, as for docker setup.
After running docker compose and seeing that it fails,
You can use the following commands:
docker ps -a // -a flag to see container ids of containers that were stopped for whatever reason as well.
Now get find the Id of the java process that exited and examine its logs:
docker logs <ID_OF_THE_EXTED_CONTAINER_GOES_HERE>
Now the chances are that the application context fails to start (maybe network related issue or something, here it's really hard to tell without seeing an actual log) and hence the issue.
Another possible issue is that the application is "too heavy" (by this I mean that it exceeds some quotas imposed on docker container).
You can run docker stats <CONTAINER_ID> command to see its memory / cpu usage in real time or gather metrics from within the application.
I think I found the solution (in this blog entry): Use exec form instead of shell form in the Dockerfile so that the SIGTERM that Docker issues hits the java process instead of the bash process (which doesn't forward signals to any child processes).
Shell form (executed with a /bin/sh -c shell):
ENTRYPOINT java -jar /app.jar
Exec form (executed without a shell):
ENTRYPOINT ["java", "-jar", "/app.jar"]
So I'm deploying my Spring Boot application on an Ubuntu LTS Server. It is built with maven and running with embedded Tomcat.
I'm still new to the deployment process, what I did was:
Log into server via ssh
use scp to upload my_application.zip
unzip it in ssh
java -jar my_application.jar
Now all of that works perfectly fine and I've been using it like that for quiet some time. Now I have to make the Application to stay online and available after logging out of the shell.
I have read some documentation about running processes in background on Linux and I've tried it with nohup java -jar myApplication.jar &, with the screen command and with bg. All of them worked fine while I'm logged into the ssh.
Here comes my problem:
As soon as I end the ssh session the Web App is still available (so the process clearly didn't stop) but it just looks & behaves really weird.
CSS is not applied, JS does not work etc.
My guess would be that some paths or file system accesses are messed up, but I have no idea at all how that could origin from the ssh session.
(When I log back into ssh everything is working fine again)
Would be great if someone has a clue here
If your server has encrypted home directory, it will get re-encrypted once you log out and therefore your script will stop working. It does not have a lot of sense to have encrypted homes on servers so you can disable it.
Or just run the script from different directory and avoid working with files under home directory.
I think you should use systemd for this case.
Also You can add new system user for your app.
You can find more information here:
Spring Boot: 59.2.2 Installation as a systemd service
Ubuntu Wiki: Systemd For UpstartUsers
For example:
Create file myunit.service
[Unit]
Description=MySpringService
After=syslog.target
After=network.target
After=mysql.service
[Service]
Type=forking
PIDFile=/work/www/myunit/shared/tmp/pids/service.pid
WorkingDirectory=/work/www/myunit/current
User=myunit
Group=myunit
Environment=RACK_ENV=production
OOMScoreAdjust=-1000
ExecStart=/usr/local/bin/bundle exec service -C /work/www/myunit/shared/config/service.rb --daemon
ExecStop=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state restart
TimeoutSec=300
[Install]
WantedBy=multi-user.target
Copy file to /etc/systemd/system/
Run:
systemctl enable myunit
systemctl start myunit
I was trying to build a JAVA web application using Docker. I was making a docker container to deploy and run the application. I am beginner. So I started with small POC for java application(jar) which was working fine. I made some changes for JAVA web application(war) and created a Dockerfile for the project which is as follows :
Dockerfile
---------------------------------------------------
FROM java:8
RUN apt-get update
RUN apt-get install -y maven
WORKDIR /code
ADD pom.xml /code/pom.xml
ADD src/main/webapp/WEB-INF/web.xml /codes/rc/main/webapp/WEB-INF/web.xml
RUN ["mvn", "dependency:resolve"]
ADD src /code/src
RUN ["mvn", "package"]
CMD ["usr/lib/jvm/java-8-openjdk-amd64/bin/java", "-war", "target/techpoint.war"]
----------------------------------------------------
Build was successful but when I run the application - It says
"Unrecognized option: -war | Error: Could not create the Java Virtual Machine | Error: A fatal exception has occurred. Program will exit"
And when I replaced "-war" with "-jar" - It says "no main manifest attribute, in target/myapp.war"
Can somebody tell me how can I make JAVA web application (war) compatible with Docker deployment process. That means what should be the actual Dockerfile (with commands) to make possible to build and run the application?
You need a web server or an application server container like tomcat or Jboss (and many others) to deploy and run your java based web application. Your "techpoint.war" files need to be copied to the specific folder depends on each web server. For example, if you are using Tomcat then you can copy it to the /webapps folder. Tomcat will extract and deploy the war file.
You can add the following to your DockerFile.
FROM tomcat:8.5.11-jre8
COPY /<war_file_location>/techpoint.war /usr/local/tomcat/webapps/techpoint.war
You can build the image using docker build command and start the container from the created image.
docker build -t techpoint.
docker run -it --rm -p 8091:8080 techpoint
Now Tomcat will extract and deploy your war file.How to access the deployed application depends on the webroot of your application. For example,
http://<ip_address>:8091/techpoint/index.html