I'm having a problem with my .war file deployment through CodePipeline (using CodeBuild) to my Elastic Beanstalk environment. After a successful pipeline deployment, it throws a 404 error (see picture).
However, when I upload the .war file from my project code directly into my Elastic Beanstalk environment, it works just fine.
Ideally, I want to just be able to run the CodePipeline to update the versioning.
My CodeBuild (buildspec) -
version: 0.2
phases:
install:
runtime-versions:
java: corretto11
build:
commands:
- ls -la
- cd prod/
- mvn clean
- mvn install
# post_build:
# commands:
artifacts:
files:
- backend/target/backend-0.0.1-SNAPSHOT.war
# name: artifact
base-directory: prod/
404 Error -
I've tried this as well and it still gives me a 404 error
version: 0.2
phases:
install:
runtime-versions:
java: corretto11
build:
commands:
- ls -la
- cd prod/
- mvn clean
- mvn install
post_build:
commands:
- mv backend/target/backend-0.0.1-SNAPSHOT.war ROOT.war
artifacts:
files:
- ROOT.war
AWS Elastic Beanstalk expects to find and run a ROOT.war at root directory.
ROOT.war runs at myapp.elasticbeanstalk.com. In a single WAR source
bundle, the application always runs at the root path.
(Source)
You have two options to resolve this
Make sure that your artifact is named ROOT.war and is found at root level (in contrary to backend/target/backend-0.0.1-SNAPSHOT.war)
Use the post_build phase in your CodePipeline to rename and move the file adequately (the easier option).
Option 2 approach:
post_build:
commands:
- mv backend/target/backend-0.0.1-SNAPSHOT.war ROOT.war
Related
I have a Spring Boot project named "BikeService". I am generating a war file for this project by using the following command in the pom.xml file
<packaging>war</packaging>
Now I want to deploy this on Elastic Beanstalk which I have creating using
Tomcat 8.5 with Java 8 running on 64bit Amazon Linux/3.3.6
After uploading the code the deployment is successful and the Health of the environment is OK but on running the environment URL it is showing HTTP 404 - Not Found.
I am using the following buildspec.yml file:
version: 0.2
phases:
install:
runtime-versions:
java: corretto11
pre_build:
commands:
- echo In the pre_build phase...
build:
commands:
- echo Build started on `date`
- mvn install
post_build:
commands:
- echo Build completed on `date`
artifacts:
files:
- target/bike-service-0.0.1-SNAPSHOT.war
- scripts/*
So the problem was solved after a lot of researching.
The issue was with the buildspec.yml file.
I am posting the correct buildspec.yml file in case anyone searches for it in the future.
The following file if for a Spring Boot project with war packaging.
version: 0.2
phases:
install:
runtime-versions:
java: corretto8
pre_build:
commands:
- echo In the pre_build phase...
build:
commands:
- echo Build started on `date`
post_build:
commands:
- echo Build completed on `date`
- mvn package
- mv target/bike-service-0.0.1-SNAPSHOT.war bike-service-0.0.1-SNAPSHOT.war
artifacts:
files:
- bike-service-0.0.1-SNAPSHOT.war
- .ebextensions/**/*
Created basic HelloWorld microservice using Spring Boot (2.1.3), Java 8, Maven.
pom.xml has maven plugin entry like below
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.HelloWorldApplication</mainClass>
</configuration>
</plugin>
Dockerfile looks like below
FROM openjdk:8
VOLUME /tmp
ADD target/helloworld.jar helloworld.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","helloworld.jar"]
Created image on local machine using command
docker build . -t helloworld:v1
Verified by creating container out of it.
Checked in code to docker-hub account and github account.
Logged into Google cloud platform (GCP), created kubernetes cluster, created pipeline(using container builder) by configuring github url where helloworld microservice code resides. There are two options to run build (use Dockerfile or cloudbuild.yaml). I am using Dockerfile to run build.
When build is picked up to run, it fails for this line in Dockerfile
ADD target/helloworld.jar helloworld.jar
Error seen in GCP logs:
ADD failed: stat /var/lib/docker/tmp/docker-builderxxxxxx/target/helloworld.jar: no such file or directory
I tried to replace it with COPY command and still the issue is same.
Note: I tried to go with cloudbuild.yaml
Here is how my cloudbuild.yaml looks:
steps:
# Build the helloworld container image.
- name: 'gcr.io/cloud-builders/docker'
args:
- 'build'
- '-t'
- 'gcr.io/${PROJECT_ID}/helloworld:${TAG_NAME}'
- '.'
This didn't make any difference. Issue remains the same.
Any idea if Springboot Java application has some specific configuration for Dockerfile to be built fine in Google Cloud Platform?
UPDATE - 1
Based on comments tried below steps on local machine:
ran command mvn clean . That cleaned target folder
updated Dockerfile
FROM maven:3.5-jdk-8 AS build
COPY src .
COPY pom.xml .
RUN mvn -f pom.xml clean package
FROM openjdk:8
VOLUME /tmp
COPY --from=build target/helloworld.jar helloworld.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","helloworld.jar"]
Ran docker build . -t helloworld:v1 command and that created image.
Then run command to start container:
docker run -p 8081:8081 -n helloworld-app -d helloworld:v1
container starts and exits with error in log:
Exception in thread "main" java.lang.ClassNotFoundException: com.example.HelloWorldApplication at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
Looks like a problem with file paths.
Try the following updated Dockerfile, which explicitly sets the working directory. It also uses explicit file paths when copying the jar between images.
FROM maven:3.5-jdk-8-slim AS build
WORKDIR /home/app
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn clean package
FROM openjdk:8-jre-slim
COPY --from=build /home/app/target/helloworld-0.0.1-SNAPSHOT.jar /usr/local/lib/helloworld.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/usr/local/lib/helloworld.jar"]
Additional Notes:
See the related answer for a full example building a spring boot app
I've based the second stage on a JRE image. Reduces the size of the output image.
I have a java project that I am hosting on GitHub. I also have a Docker file that creates an image based off of the generated war files after a build (using Maven).
What I want is for a new Docker image to be generated every time I push new code to the repo. What I am getting confused with is how will Docker build the source and add the generated .war files to the base Tomcat Docker file? Or am I thinking about this wrong?
Alternatively is there a way for Travis CI to generate the war and then push it to a docker image?
So to fix this, I had Travis CI pull data from the repo and after the build have the docker file pull the artifacts from the target directory and push the built docker image to docker hub.
.travis.yml
language: java
sudo: true
services:
- docker
cache:
directories:
- $HOME/.m2
jdk:
- oraclejdk8
os:
- linux
branches:
only:
- master
after_success:
- docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
- docker build -t blah/blah .
- docker push blah/blah
Dockerfile:
# Pull base image
From tomcat:8-jre8
# Maintainer
MAINTAINER "Joel"
# Copy to images tomcat path
COPY target/blah*.war /usr/local/tomcat/webapps/sacred-text-api.war
I have a JHipster project I want to build through Travis CI and then deploy to Heroku. However, even if Travis CI passes the build, it commits the whole code to Heroku and then Heroku tries to build the whole project again, defeating the purpose of having Travis CI in the middle.
Is there a way to build my project with Travis CI and then just deploy the build WAR to Heroku?
Given the fact that JHipster uses Spring Boot, I would only need the WAR to run the application.
Here is my .travis.yml files:
language:
- java
jdk:
- oraclejdk8
sudo: false
env:
- MAVEN_CUSTOM_OPTS="-Pprod,heroku -DskipTests"
before_install:
- npm install -g npm
- rm -fr /home/travis/.npm/
- npm cache clean -g
- npm install grunt-cli -g
- npm install
install:
- mvn package -Pprod -DskipTests
script: true
notifications:
webhooks:
on_success: change
on_failure: always
on_start: false
deploy:
provider: heroku
api_key:
secure: [key]
skip_cleanup: true
Also, if there is another way to deploy a Spring Boot application through this process, it would be great.
Thank you.
You can install the heroku-deploy plugin on Travis CI and deploy the same way you deploy to Heroku locally.
In fact, this is what the heroku-deploy plugin does to test itself, so you can use it as an example. The setup script downloads the Ubuntu installer for the toolbelt from: https://toolbelt.heroku.com/install-ubuntu.sh
Then you'll only need to install the plugin with this command in your setup script:
heroku plugins:install https://github.com/heroku/heroku-deploy
And set your API key as a secure variable in the .travis.yml
I'm deploying an application that requires Maven 3.0.4 to the Heroku Cedar stack, but the build fails with this warning:
Rule 1: org.apache.maven.plugins.enforcer.RequireMavenVersion failed with message:
Build with Maven 3.0.4 or later. Maven 3.0 through 3.0.3 inclusive do not pass
correct settings.xml to Maven Release Plugin.
I believe that this failure is caused by this Maven bug:
REGRESSION: Injected Settings in a Mojo are missing the profiles from settings.xml.
Is there any way I can configure Heroku Cedar to use a different version of Maven?
Fork the Heroku Java Buildpack git repository, then clone it.
Open bin/compile in your editor. Look for the following lines:
# install maven with base repository
MAVEN_URL="http://s3.amazonaws.com/heroku-jvm-langpack-java/maven.tar.gz"
if [ ! -d .maven ]; then
echo -n "-----> Installing Maven 3.0.3..."
curl --silent --max-time 60 --location $MAVEN_URL | tar xz
chmod +x .maven/bin/mvn
echo " done"
fi
Change the MAVEN_URL to download Maven 3.0.4 from Apache:
MAVEN_URL="http://www.us.apache.org/dist/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz"
Commit your changes, then configure your Heroku Cedar instance to use your custom buildpack:
heroku config:add BUILDPACK_URL=[YOUR GITHUB REPO] --app [YOUR HEROKU CEDAR APP]
For details, see Heroku's instructions Using a Custom Buildpack.
It is possible to do it as long as you create your own build pack. Have a look at what I did to use maven 3.0.4 at https://github.com/jtzikas/heroku-buildpack-java.
In short what I had to do, was to change the uri of the location of maven but also change the directory structure since the heroku one contains the .m2 and the .maven directory. Those directories are needed in order for the rest of the script to run.
# install maven without base repository
MAVEN_URL="http://www.us.apache.org/dist/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz"
if [ ! -d .maven ]; then
echo -n "-----> Installing Maven 3.0.4..."
curl --silent --max-time 60 --location $MAVEN_URL | tar xz
mv apache-maven-3.0.4 .maven
mkdir .m2
chmod +x .maven/bin/mvn
echo " done"
fi
The .m2 directory is the repository location and the .maven directory is the location of the maven installation. You will need to extract the maven 3.0.4 into the .maven directory and not the apache-maven-3.0.4 that is the root of directory of maven 3.0.4. Dont forget that you need to create an empty .m2 directory to host the maven repository
Check the heroku documentation for instruction on how to use custom buildpacks.