I have a java spring-boot import application that currently runs periodically by cron.
Now I'd like to migrate to docker, the app already runs fine inside a container (docker-compose) with:
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Question: how can I prevent the docker container being killed by gitlab CIC/D while my script is still running - when a new software version is being deployed? the docker host should wait until the script finished (how could I signal that to the host), and only then publish and run the new container version.
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 am new to Java. I have hapi fhir server running on AWS by cloning this repository (https://github.com/hapifhir/hapi-fhir-jpaserver-starter)
I run my server with follwing command: "sudo mvn -e jetty:run"
--
My Problem:
As soon as I log out of AWS, my server stops. When I am logged in to my AWS instance via the .pem file, AWS instance running with ubuntu 18.04 LTS with nginx server.
Thanks
The ideal approach to execute or setup a java application on AWS is to run it as a daemon by setting up systemd script or init in linux.
In your case the application stops as soon as you close the terminal, because you are starting it in the terminal without the nohup command, when the terminal is closed the application is also stopped since the controlling thread is stopped. If you just want to launch the application on a separate background thread without going through the hassle of actually setting it up as a service in linux , you can use the nohup command (setting up a systemd to register the java application as a service is the preferred approach) :
nohup java -jar yourjarName &
run it as daemon:
"sudo mvn -e jetty:run &"
The & makes the command run in the background.
From man bash:
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
I want to run a Java Spring application inside of a docker container and this application should be able to deploy sibling containers. When I run the Java application directly on my machine it works fine and can deploy containers, but as soon as I try to run the application inside a container it does not work any more (im using supervisord to run the mongodb and Java Spring app in one container and I know that thats not best practice). The container starts up fine, but crashes as soon as my application tries to connect to the docker deamon without any stacktraces from Java, just the error WARN received SIGTERM indicating exit request. The supervisord logs dont contain additional info.
I tried mounting the docker socket from the host (Windows 10 Pro with Docker Desktop, also tried Ubuntu Server 18.04) into the container using -v /var/run/docker.sock:/var/run/docker.sock.
I also tried to use --net="host".
Both did not work, although with the second one the container does not crash but produces a different error ({}->unix://localhost:80: Connection refused) visible in the log of my java application, which indicates that it cant even find the right address for the deamon.
I also activated "Expose deamon on tcp://localhost:2375 without TLS".
I also tried to set the DOCKER_HOST environment variable inside the container to default values such as "tcp://localhost:2375" or "/var/run/docker.sock".
Here is the code that I use to initialize the docker client.
DockerClient docker = DefaultDockerClient.fromEnv().build();
The DefaultDockerClient.fromEnv().build(); should create a docker client that uses the DOCKER_HOST environment variable to connect to the host or the default adress ("/var/run/docker.sock" on *NIX).
Here is my DOCKERFILE:
FROM openjdk:8-jre-alpine
ENV PACKAGES mongodb supervisor
VOLUME /opt/server
VOLUME /data/db
WORKDIR /opt/accservermanager
ADD supervisord.conf /etc/supervisor.conf
ADD accservermanager.jar /opt/accservermanager/accservermanager.jar
ADD application.properties /opt/accservermanager/application.properties
RUN apk update && \
apk add --update $PACKAGES --no-cache && \
rm -rf /var/cache/apk/*
EXPOSE 8000
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor.conf"]
And finally, my supervisord.conf
[supervisord]
user=root
stderr_logfile=/var/log/supervisord.err.log
stdout_logfile=/var/log/supervisord.out.log
loglevel=debug
[program:mongodb]
command=mongod --smallfiles
autostart=true
autorestart=true
stderr_logfile=/var/log/mongo.err.log
stdout_logfile=/var/log/mongo.out.log
[program:accservermanager]
directory=/opt/accservermanager/
command=java -jar accservermanager.jar
autostart=true
autorestart=true
stderr_logfile=/var/log/accservermanager.err.log
stdout_logfile=/var/log/accservermanager.out.log
Expected result: Application connects to the docker client from the host and is able to deploy/manage containers on the host
Actual result: Container crashes or outputs errors.
Turns out that there is a new version of spotify-docker that fixes my problem.
Updating from v8.15.1 to v8.15.2 solved my issue.
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"]
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.