Tomcat in Docker deploying War file - HTTP Status 404 – Not Found - spring-boot

I have created a Spring Boot web API. With the help of Docker the web API is containerized. The Dockerfile you can find below.
When I build the Dockerfile and run it with this command: docker container run -p 8080:8080 --name backend b7908762020, the container is being created. When I navigate to http://localhost:8080/mywar then it shows "HTTP Status 404 – Not Found".
Why is that the case? Is my Dockerfile correct?
FROM maven:3.3.9-jdk-8-alpine as build-env
COPY pom.xml /tmp/
COPY settings.xml /root/.m2/settings.xml
COPY src /tmp/src/
WORKDIR /tmp/
RUN mvn package -Dmaven.test.skip=true
FROM tomcat:8.0
COPY --from=build-env /tmp/target/cbm-server-0.0.1-SNAPSHOT.war $CATALINA_HOME/webapps/cbm-server.war
# The env variabel to pickup the correct environment properties file
ADD setenv.sh $CATALINA_HOME/bin/setenv.sh
ADD tomcat-users.xml $CATALINA_HOME/conf/tomcat-users.xml
EXPOSE 8009
EXPOSE 8080
CMD ["catalina.sh", "run"]

Related

Laravel Vite manifest.json deploy with docker

I have project with Laravel 9 and Vite and faced the problem when deploy app to host. I use docker, docker-compose and Gitlab CI/CD
TL;DR - manifest.json from vite must be accessible from app container, but assets build and store in other container. How can i send this file to app container?
My flow:
Push tag to Gitlab and start CI/CD
(Build stage) Build docker containers
app container with Laravel exposing php-fpm
web container with Nginx proxy requests to app and host static files
(public/build)
(Prepare stage) Clean containers from dev dependencies and upload to registry
(Deploy stage) Start docker-compose service on the host with builded containers
The problem is in manifest.json file from Vite. This is web Dockerfile:
FROM nginx:1.15.3 as base
COPY ./deployment/dockerfiles/web/default.conf /etc/nginx/conf.d/default.conf
WORKDIR /var/www/public
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
FROM node:16.15.1-alpine as builder
WORKDIR /source
COPY ./package.json /source/
COPY ./yarn.lock /source/
RUN yarn install --frozen-lockfile
COPY ./vite.config.js /source
COPY ./resources/js /source/resources/js
COPY ./resources/css /source/resources/css
RUN yarn run build
FROM base
COPY --from=builder /source/public .
CMD ["service", "nginx", "start"]
For now, i have /public/build/ directory in web container with manifest.json and assets, but app container dont know about it - and when i start service - face the exception
Vite manifest not found at: /var/www/public/build/manifest.json
For now, i solve this problem in deploy stage - after docker-compose up just copy file from web service to app service - but this not look like production ready solution - because container in registry not ready to start without manipulation with service.
Then, question - how can i share manifest.json to app container on build stage? Or any other way?

How to pass application.properties to SpringBoot app in Docker container?

Assume we have a simple Dockerfile where my_sb_app.jar is a SpringBoot application:
FROM bellsoft/liberica-openjdk-alpine:11.0.9-12
WORKDIR /app
COPY target/my_sb_app.jar /app
EXPOSE 8080
ENTRYPOINT java -jar my_sb_app.jar
I would like to pass custom app.properties on each run
docker run my_image_name /somewhere/on/my/host/app.properties
so the expected final command (inside the container) could be identical to the following
java -jar my_sb_app.jar --spring.config.location=%%file_with_contents_of_app.properties%%
What is the standard way of passing a file into a Docker container?
How the Docker image sould be changed?
The standard way to pass files from host to the container is with volumes:
https://docs.docker.com/storage/bind-mounts/
https://docs.docker.com/storage/volumes/
In your example:
docker run -v /somewhere/on/my/host/app.properties:/opt/app.properties my_image_name
java -jar my_sb_app.jar --spring.config.location=/opt/app.properties

unable to run docker container as getting this error:Unable to access jarfile app.jar

I have created the image using below Docker file.Its working fine in local when I run it in the container using this image[docker run -p 80:8080 username/spring-boot-docker-aws-demo:tag
FROM openjdk:8-jdk-alpine
COPY target/spring-boot-docker-aws-demo.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
I have pushed this image to Docker hub to run it in EC2 instance.when I run it its saying "Error: Unable to access jarfile app.jar"
https://hub.docker.com/layers/chaituu/spring-boot-docker-aws-demo/docker-aws-demo-tag/images/sha256-110363a016eb2250264d96c8890dede518d8e519fdc9a27174334fe1096a540e?context=repo
what could be the issue?
I had a similar issue today (although in my case it wouldn't even run locally). Here's what your Dockerfile would look like with my fix:
FROM openjdk:8-jdk-alpine
COPY target/spring-boot-docker-aws-demo.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["sh"]
CMD ["-c", "java -jar /app/app.jar"]

How to add storage using Volume in a Docker container

I have a spring boot application and I want to start it on a docker container. However, I want to persist data, so I do not have to rebuild image to see the changes I made to RestAPI.
My docker file
FROM maven:3.6.1-jdk-8-alpine
RUN mkdir -p /usr/src
WORKDIR /usr/src
COPY . /usr/src/
RUN mvn clean install
WORKDIR /usr/src/target
ENTRYPOINT ["java", "-jar", "SecurityAndDocker-0.0.1-SNAPSHOT.jar"]
EXPOSE 8080:8080
Image build is ok
Running docker run -p 8080:8080 image-name works perfectly fine
How would I attach a volume to this application?
Thank you!
you can mount the volume, while running the container.
docker run -d -p 8080:8080 --name <container-name> --mount source=myvol2,target=/app <image-name>
you can also read the documentation: https://docs.docker.com/storage/volumes/
Feel free to ask in case you found any issue.
If I understand you want the target directory to be extracted out in a volume from your custom image's container.
use VOLUME keyword to specify the directory.
Your dockerfile should go like this.
FROM maven:3.6.1-jdk-8-alpine
RUN mkdir -p /usr/src
WORKDIR /usr/src
COPY . /usr/src/
RUN mvn clean install
VOLUME /usr/src/target
WORKDIR/usr/src/target
ENTRYPOINT ["java", "-jar", "SecurityAndDocker-0.0.1-SNAPSHOT.jar"]
EXPOSE 8080:8080
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If you want to save the working directory just add VOLUME in your dockerfile.

Heroku run Docker image with port parameter

When I push an existing Docker image to Heroku, Heroku provides a $PORT environment variable. How can I pass this property to the Heroku run instance?
On localhost this would work:
docker pull swaggerapi/swagger-ui
docker run -p 80:8080 swaggerapi/swagger-ui
On Heroku I should do:
docker run -p $PORT:8080 swaggerapi/swagger-ui
Is something like this possible?
The question is quite old now, but still I will write my answer here if it can be of some help to others.
I have spring-boot App along with swagger-ui Dockerized and deployed on Heroku.
This is my application.yml looks like:
server:
port: ${PORT:8080}
forward-headers-strategy: framework
servlet:
contextPath: /my-app
springdoc:
swagger-ui:
path: '/swagger-ui.html'
Below is my DockerFile configuration.
FROM maven:3.5-jdk-8 as maven_build
WORKDIR /app
COPY pom.xml .
RUN mvn clean package -Dmaven.main.skip -Dmaven.test.skip && rm -r target
COPY src ./src
RUN mvn package spring-boot:repackage
########run stage########
FROM openjdk:8-jdk-alpine
WORKDIR /app
RUN apk add --no-cache bash
COPY --from=maven_build /app/target/springapp-1.1.1.jar ./
#run the app
# 256m was necessary for me, as I am using free version so Heroku was giving me memory quota limit exception therefore, I restricted the limit to 256m
ENV JAVA_OPTS "-Xmx256m"
ENTRYPOINT ["java","${JAVA_OPTS}", "-jar","-Dserver.port=${PORT}", "springapp-1.1.1.jar"]
The commands I used to create the heroku app:
heroku create
heroku stack:set container
The commands I used to build image and deploy:
docker build -t app-image .
heroku container:push web
heroku container:release web
Finally make sure on Heroku Dashboard the dyno information looks like this:
web java \$\{JAVA_OPTS\} -jar -Dserver.port\=\$\{PORT\} springapp-1.1.1.jar
After all these steps, I was able to access the swagger-ui via
https://testapp.herokuapp.com/my-app/swagger-ui.html
Your Docker container is required to listen to HTTP traffic in the port specified by Heroku.
Looking at the Dockerfile in the Github repo for swaggerapi/swagger-ui, it looks like it already supports the PORT environment variable: https://github.com/swagger-api/swagger-ui/blob/be72c292cae62bcaf743adc6236707962bc60bad/Dockerfile#L13
So maybe you don't really need to do anything?
It looks like this image would just work, if shipped to Heroku as a web app.

Resources