Spring boot app runs fine standalone, errs in docker - docker

I have a spring-boot based java application which runs fine from the command line (embedded tomcat standalone).
Problem
When I run the app in docker, it does not run correctly. The console shows the application starts up fine with no errors; however, the browser displays the following error page:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing
this as a fallback.
[I understand the message says no mapping for '/error' url. However I want to know the root cause ]
Additional Info/Context
Spring boot 1.4.2
docker plugin
Output is 'war' file which also runs standalone
I run docker image in 'host' networking mode (--net=host) so it can access the database (mysql running on my localhost)
build.gradle target
task buildDocker(type: Docker, dependsOn: build) {
push = false
applicationName = jar.baseName
dockerfile = file('src/main/docker/Dockerfile')
doFirst {
copy {
from war
into stageDir
}
}
}
dockerfile
FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD floss.war app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
Command to Run Docker
dockerImg=1248c47d9cfa
docker run \
-it \
--net=host \
-e SPRING_APPLICATION_JSON="$SPRING_APPLICATION_JSON" \
$dockerImg
I'm new to docker and would appreciate any suggestions.
thanks in advance!

Problems:
No exposed port in dockerfile
No port mapping with host.
Sol:
1. expose application port in dockerfile and build image
EXPOSE $application_port
2. then run
docker run -p 8080:8080 -d -e SPRING_APPLICATION_JSON="$SPRING_APPLICATION_JSON" $dockerImg

I had the same issue. You seem to be using the same Docker example for Spring Boot as I was. As you can see, the WAR file gets a .jar extension when it is placed into the Docker image, not .war.
I was able to solve the issue by calling the file "app.war" instead of "app.jar" and changing the Java startup parameters accordingly.
If you use the extension ".jar", the access to static resources works fine, but accessing all dynamic content (JSPs, ...) leads to a 404 error.

i suspect it is due to the missing -p option, can you try this. change the port if it is different.
docker run -p 8080:8080
-it \
--net=host \
-e SPRING_APPLICATION_JSON="$SPRING_APPLICATION_JSON" \
$dockerImg

Related

Docker run commands works but dockerfile not

I have a problem with running the image of Dockerfile. CLI commands work fine but when I use the Dockerfile I get an error from the localhost:
localhost didn’t send any data.
What I am doing is simple. By CLI:
docker run -d --name mytomcat -p 8080:8080 tomcat:latest
docker exec -it mytomcat /bin/bash
mv webapps webapps2
mv webapps.dist/ webapps
exit
Which works fine.
My Dockerfile:
FROM tomcat:latest
CMD mv webapps webapps2 && mv webapps.dist/ webapps && /bin/bash
Build and run:
docker build -t myrepo/tomacat:1.00 .
docker run -d --name mytomcat -p 8080:8080 myrepo/tomacat:1.00
Doesn't work and show the above error.
Note: I am using mv command because I get 404 error!
Does anybody know the problem here?
When your Dockerfile has a CMD command, that runs instead of the command in the base image. With the tomcat image, the base image would run the Tomcat server; but with this Dockerfile, it's trying to run a bash shell instead, and without any input that just exits immediately.
To just moves files around, it's usually better to use COPY and RUN directives to set up the image once, rather than trying to repeat these steps every time you run the container. For this setup where the base image already has a reasonable CMD, you don't need to repeat it in your own custom Dockerfile.
FROM tomcat:latest
RUN mv webapps webapps2 && mv webapps.dist/ webapps
# no particular mention of bash; use the `CMD` from the base image
It's not uncommon for a base image to include some sort of runtime that needs to be configured, but for the base image's CMD to still be correct. In addition to tomcat, nginx and php:fpm work similarly; so long as their configuration files and code are in the right place, you don't need to repeat the CMD.

How to properly expose/publish ports for a WebUI-based application in Docker?

I'm trying to port this webapp to Docker. I wrote the following Dockerfile:
FROM anapsix/alpine-java
MAINTAINER <name>
COPY aard2-web-0.7-java6.jar /home/aard2-web-0.7-java6.jar
COPY start.sh /home/start.sh
CMD ["bash", "/home/start.sh"]
EXPOSE 8013/tcp
Here are the contents of start.sh:
#!/bin/bash
java -Dslobber.browse=true -jar /home/aard2-web-0.7-java6.jar /home/dicts/*.slob
Then I built the image:
docker build -t aard2-docker .
And I used the following command to run the container:
docker run --name Aard2 -p 127.0.0.1:8013:8013 -v /home/<name>/dicts:/home/dicts aard2-docker
The app is running normally, prompting that it's listening at http://127.0.0.1:8013. However, I opened the address only to find that I couldn't connect to the app.
I tried using the EXPOSE command (as shown in the Dockerfile snippet above) and variants of the -p flag, such as -p 127.0.0.1:8013:8013, -p 8013:8013, -p 8013:8013/tcp, but none of them worked.
How can I expose/publish the port to 127.0.0.1 properly? Thanks!
Here's the response from the original author:
you need to tell the server to listen on all network interfaces instead of localhost - that is you are missing -Dslobber.host=0.0.0.0
this works for me:
FROM anapsix/alpine-java
COPY ./build/libs/aard2-web-0.7.jar /home/aard2-web-0.7.jar
CMD ["bash", "-c", "java -Dslobber.host=0.0.0.0 -jar /home/aard2-web-0.7.jar /dicts/*.slob"]
EXPOSE 8013/tcp
and then run like this:
docker run -v $HOME/Downloads:/dicts -p 8013:8013 --rm aard2-web
-Dslobber.browse=true opens default browser, I don't think this has any effect in docker so don't need that.
https://github.com/itkach/aard2-web/issues/12#issuecomment-895557949

docker file for tomcat

I wrote one docker file for tomcat installation, the file is
FROM openjdk:8-jre-alpine
RUN wget http://mirrors.fibergrid.in/apache/tomcat/tomcat-8/v8.5.34/bin/apache-tomcat-8.5.34.tar.gz
RUN gzip apache-tomcat-8.5.34.tar.gz
ADD https://github.com/spagop/quickstart/raw/master/management-api-examples/mgmt-deploy-application/application/jboss-as-helloworld.war /apache-tomcat-8.5.34/*/webapps
EXPOSE 8080
CMD ["catalina.sh", "run"]
And I built the above docker file by using
$ docker build -t tomacat -f docker file name .
And created the container by using above docker image, command is
$ docker run --name=tom1 -d -it -p 9090:8080 tomcat
After running the docker run container is up and running
But tomcat server is not up and running in background
I replaced the catalina.sh with startup.sh in CMD area and also i getting same problem
Please help me for resolving problem
As mentioned in the question, I did everything as stated and started a container. After that I accessed the tomcat through HOST_IP:HOST_PORT and I was able to access the Tomcat. The issue may be that you are not accessing the Tomcat correctly like HOST_IP is not correct.

Spring Boot in Docker

I am learning how to use Docker with a Spring Boot app. I have run into a small snag and I hope someone can see the issue. My application relies heavily on #Value that are set in environment specific properties files. In my /src/main/resources I have three properties files
application.properties
application-local.properties
application-prod.properties
I normally start my app with:
java -jar -Dspring.profiles.active=local build/libs/finance-0.0.1-SNAPSHOT.jar
and that reads the "application-local.properties" and runs properly. However, I am using this src/main/docker/DockerFile:
FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD finance-0.0.1-SNAPSHOT.jar finance.jar
RUN sh -c 'touch /finance.jar'
EXPOSE 8081
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /finance.jar" ]
And then I start it as:
docker run -p 8081:80 username/reponame/finance
-Dspring.profiles.active=local
I get errors that my #Values are not found:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.driverClassName' in value "${spring.datasource.driverClassName}"
However, that value does exist in both *.local & *.prop properties files.
spring.datasource.driverClassName=org.postgresql.Driver
Do I need to do anything special for that to be picked up?
UPDATE:
Based upon feedback from M. Deinum I changing my startup to be:
docker run -p 8081:80 username/reponame/finance
-eSPRING_PROFILES_ACTIVE=local
but that didn't work UNTIL I realized order matter, so now running:
docker run -e"SPRING_PROFILES_ACTIVE=test" -p 8081:80 username/reponame/finance
works just fine.
You can use docker run Using Spring Profiles. Running your freshly minted Docker image with Spring profiles is as easy as passing an environment variable to the Docker run command
$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
You can also debug the application in a Docker container. To debug the application JPDA Transport can can be used. So we’ll treat the container like a remote server. To enable this feature pass a java agent settings in JAVA_OPTS variable and map agent’s port to localhost during a container run.
$ docker run -e "JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker
Resource Link:
Spring Boot with Docker
Using spring profile with docker for nightly and dev build:
Simply set the environment varialbe SPRING_PROFILES_ACTIVE when starting the container. This will switch the active of the Spring Application.
The following two lines will start the latest Planets dev build on port 8081 and the nightly build on port 8080.
docker run -d -p 8080:8080 -e \"SPRING_PROFILES_ACTIVE=nightly\" --name nightly-planets-server planets/server:nightly
docker run -d -p 8081:8080 -e \"SPRING_PROFILES_ACTIVE=dev\" --name dev-planets-server planets/server:latest
This can be done automatically from a CI system. The dev server contains the latest build and nightly will be deployed once a day...
There are 3 different ways to do this, as explained here
Passing Spring Profile in Dockerfile
Passing Spring Profile in Docker
run command
Passing Spring Profile in DockerCompose
Below an example for a spring boot project dockerfile
<pre>FROM java:8
ADD target/my-api.jar rest-api.jar
RUN bash -c 'touch /pegasus.jar'
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=dev","-jar","/rest-api.jar"]
</pre>
You can use the docker run command
docker run -d -p 8080:8080 -e "SPRING_PROFILES_ACTIVE=dev" --name rest-api dockerImage:latest
If you intend to use the docker compose you can use something like this
version: "3"
services:
rest-api:
image: rest-api:0.0.1
ports:
- "8080:8080"
environment:
- "SPRING_PROFILES_ACTIVE=dev"
More description and examples can be found here

Docker add warfile to official Tomcat image

I pulled official Docker image for Tomcat by running this command.
docker run -it --rm tomcat:8.0
By using this as base image I need to build new image that contains my war file in the tomcat webapps folder. I created Dockerfile like this.
From tomcat8
ADD warfile /usr/local/tomcat
When I run this Dockerfile by building image I am not able to see Tomcat front page.
Can anybody tell me how to add my warfile to official Tomcat images webapp folder.
Reading from the documentation of the repo you would do something like that
FROM tomcat
MAINTAINER xyz
ADD your.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
Then build your image with docker build -t yourName <path-to-dockerfile>
And run it with:
docker run --rm -it -p 8080:8080 yourName
--rm removes the container as soon as you stop it
-p forwards the port to your host (or if you use boot2docker to this IP)
-it allows interactive mode, so you see if something get's deployed
Building on #daniel's answer, if you want to deploy your WAR to the root of tomcat, I did this:
FROM tomcat:7-jre7
MAINTAINER xyz
RUN ["rm", "-fr", "/usr/local/tomcat/webapps/ROOT"]
COPY ./target/your-webapp-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh", "run"]
It deletes the existing root webapp, copies your WAR to the ROOT.war filename then executes tomcat.
docker run -it --rm --name MYTOMCAT -p 8080:8080 -v .../wars:/usr/local/tomcat/webapps/ tomcat:8.0
where wars folder contains war to deploy
How do you check the webapps folder?
The webapps folder is within the docker container.
If you want to access your webapps container you could mount a host directory within your container to use it as webapps folder. That way you can access files without accessing docker.
Details see here
To access your logs you could do that when you run your container e.g.
docker run -rm -it -p 8080:8080 **IMAGE_NAME** /path/to/tomcat/bin/catalina.sh && tail -f /path/to/tomcat/logs
or you start your docker container and then do something like:
docker exec -it **CONTAINER_ID** tail -f /path/to/tomcat/logs
If you are using spring mvc project then you require server to run your application suppose you use tomcat then you need base image of tomcat that your application uses which you can specify through FROM command.
You can set environment variable using ENV command.
You can additionally use RUN command which executes during Docker Image buiding.
eg to give read write execute permissions to webapps folder for tomcat to unzip war file
RUN chmod -R 777 $CATALINA_HOME/webapps
And one more command is CMD. Whatever you specifying in CMD command it will execute at a time of container running. You can specify options in CMD command using double quotes(" ") seperated by comma(,).
eg
CMD ["catalina.sh","start"]
(NOTE : Remember RUN command execute at a time of image building and CMD execute at a time of running container this is confusing for new users).
This is my Dockerfile -
FROM tomcat:9.0.27-jdk8-openjdk
VOLUME /tmp
RUN chmod -R 777 $CATALINA_HOME/webapps
ENV CATALINA_HOME /usr/local/tomcat
COPY target/*.war $CATALINA_HOME/webapps/myapp.war
EXPOSE 8080
CMD ["catalina.sh","run"]
Build your image using command
docker build -t imageName <path_of_Dockerfile>
check your docker image using command
docker images
Run image using command
docker run -p 9999:8080 imageName
here 8080 is tomcat port and application can access on 9999 port
Try accessing your application on
localhost:9999/myapp/

Resources