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}
I have a spring boot application that is dockerized. By default the application has spring.cloud.config.enabled=false hence the application doesn't pick up the application.properties from configserver. However while deploying in a separate env we need to integrate the application with configserver so we need to override and set the spring.cloud.config.enabled property to true.
To achieve this I am running the docker image using the following docker-compose file :
version: '3'
services:
my-app-new:
container_name: my-app
image: my-app:1.0.0-SNAPSHOT
ports:
- "8070:8070"
environment:
- SPRING_CLOUD_CONFIG_ENABLED=true
- SPRING_CLOUD_CONFIG_URI=http://localhost:14180
However, it just doesn't work. If I hard code the values in the property file then it integrates fine.
I also tried the following command but it still didn't work :
docker run -p 8070:8070 -e SPRING_CLOUD_CONFIG_ENABLED=true -e SPRING_CLOUD_CONFIG_URI=http://localhost:14180 my-app:1.0.0-SNAPSHOT
The spring boot version is 2.2.6.
Let me know what the problem is.
Update :
I cannot use profiles as there too many env in our company and even the VMs keep getting changed so cannot have hardcoded profiles. We want a solution where we can just pass certain variables from the outside.
As someone pointed out in the comments the above compose yml is not working as the environment variables need to read by the spring boot application. So did some research on the internet and instead we are now passing the JAVA_OPTS tomcat variable while running the image. Like so :
docker run --env JAVA_OPTS="-Dspring.cloud.config.uri=http://localhost:14180 -Dspring.cloud.config.enabled=true" -p 8080:8080 my-app-image
And in the docker file we have used the JAVA_OPTS while starting the jar like so
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar" ]
And this still doesnt work. Not sure what is going wrong.
I found the problem with my setup. I made a silly error. The config server is not in my docker network and I used localhost to communicate with the config server. Localhost would of course mean that I am referring to the app containers IP which only has the app running. Instead when I used the ip address or the hostname of my machine my application container could connect to the config server successfully.
Why you not run container --> go inside --> change configuration and commit to new images.
After that deploy to new env.
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.
Spring boot's preferred deployment method is via a executable jar file which contains tomcat inside.
It is started with a simple java -jar myapp.jar.
Now, I want to deploy that jar to my linux server on EC2, am I missing something or do I really need to create a init script to properly start the application as a daemon?
If I simply call java -jar the application dies when I log out.
I could start it in screen or nohup but that is not very elegant and a restart in my server would force me to log in and start the process manually.
So, is there something already for the task in spring boot?
Please note that since Spring Boot 1.3.0.M1, you are able to build fully executable jars using Maven and Gradle.
For Maven, just include the following in your pom.xml:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
For Gradle add the following snippet to your build.gradle:
springBoot {
executable = true
}
The fully executable jar contains an extra script at the front of the file, which allows you to just symlink your Spring Boot jar to init.d or use a systemd script.
init.d example:
$ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp
This allows you to start, stop and restart your application like:
$/etc/init.d/yourapp start|stop|restart
Or use a systemd script:
[Unit]
Description=yourapp
After=syslog.target
[Service]
ExecStart=/var/yourapp/yourapp.jar
User=yourapp
WorkingDirectory=/var/yourapp
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
More information at the following links:
Installation as an init.d service
Installation as a systemd service
By far the most easiest and reliable way to run Spring Boot applications in production is with Docker. Use Docker Compose, Docker Swarm or Kubernetes if you need to use multiple connected services.
Here's a simple Dockerfile from the official Spring Boot Docker guide to get you started:
FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
An even better approach for building Docker images is to use Jib, an open-source Java tool maintained by Google for building Docker images of Java applications. Jib does not need a Dockerfile, you just invoke it with Maven (official quickstart here) or Gradle (official quickstart here).
Here's a sample command line to run the container as a daemon:
docker run \
-d --restart=always \
-e "SPRING_PROFILES_ACTIVE=prod" \
-p 8080:8080 \
prefix/imagename
My Spring boot application has two initializers. One for development and another for production. For development, I use the main method like this:
#SpringBootApplication
public class MyAppInitializer {
public static void main(String[] args) {
SpringApplication.run(MyAppInitializer .class, args);
}
}
My Initializer for production environment extends the SpringBootServletInitializer and looks like this:
#SpringBootApplication
public class MyAppInitializerServlet extends SpringBootServletInitializer{
private static final Logger log = Logger
.getLogger(SpringBootServletInitializer.class);
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
log.trace("Initializing the application");
return builder.sources(MyAppInitializerServlet .class);
}
}
I use gradle and my build.gradle file applies 'WAR' plugin. When I run it in the development environment, I use bootrun task. Where as when I want to deploy it to production, I use assemble task to generate the WAR and deploy.
I can run like a normal spring application in production without discounting the advantages provided by the inbuilt tomcat while developing. Hope this helps.
On Windows OS without Service.
start.bat
#ECHO OFF
call run.bat start
stop.bat:
#ECHO OFF
call run.bat stop
run.bat
#ECHO OFF
IF "%1"=="start" (
ECHO start myapp
start "myapp" java -jar -Dspring.profiles.active=staging myapp.jar
) ELSE IF "%1"=="stop" (
ECHO stop myapp
TASKKILL /FI "WINDOWTITLE eq myapp"
) ELSE (
ECHO please, use "run.bat start" or "run.bat stop"
)
pause
In a production environment you want your app to be started again on a machine restart etc, creating a /etc/init.d/ script and linking to the appropriate runlevel to start and stop it is the correct approach. Spring Boot will not extend to covering this as it is a operating system specific setup and the are tonnes of other options, do you want it running in a chroot jail, does it need to stop / start before some other software etc.
You can use the application called Supervisor.
In supervisor config you can define multiple services and ways to execute the same.
For Java and Spring boot applications the command would be
java -jar springbootapp.jar.
Options can be provided to keep the application running always.So if the EC2 restart then Supervisor will restart you application
I found Supervisor easy to use compared to putting startup scripts in /etc/init.d/.The startup scripts would hang or go into waiting state in case of errors .
If you are using gradle you can just add this to your build.gradle
springBoot {
executable = true
}
You can then run your application by typing ./your-app.jar
Also, you can find a complete guide here to set up your app as a service
56.1.1 Installation as an init.d service (System V)
http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
cheers
I start applications that I want to run persistently or at least semi-permanently via screen -dmS NAME /path/to/script. As far as I am informed this is the most elegant solution.
This is a simple, you can use spring boot maven plugin to finish your code deploy.
the plugin config like:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}
</jvmArguments>
<profiles>
<profile>test</profile>
</profiles>
<executable>true</executable>
</configuration>
</plugin>
And, the jvmArtuments is add for you jvm. profiles will choose a profile to start your app. executable can make your app driectly run.
and if you add mvnw to your project, or you have a maven enveriment. You can just call./mvnw spring-boot:run for mvnw or mvn spring-boot:run for maven.