3
votes

I am building my spring boot application using maven and google cloud build but somehow I get different deployment results whether I run locally using mvn appengine:run or that I deploy using Cloud Build.

If I run locally using mvn appengine:run, I can access my controller as expected. Using Cloud Build, I get a 404 error.

My cloudbuild.yaml is the following:

steps:
- name: 'gcr.io/cloud-builders/mvn'
  args: ['package']
- name: 'gcr.io/cloud-builders/gcloud'
  args: ['app', 'deploy', 'target/myapp/WEB-INF/appengine-web.xml']

How would you recommend configuring a cloud build in order to build and deploy a spring boot application on google app engine?


After additionnal digging, the issue seems to be related to some kind of error returned:

javax.servlet.ServletContext log: 2 Spring WebApplicationInitializers detected on classpath

I do not get this message in the stack trace when deploying from local machine using mvn appengine:deploy

My question still remains, how do I go about creating a cloudbuild.yaml that can invoke mvn appengine:deploy ?

1
@Anton appengine:deploy works great from my local machine but doesn't work from cloud build. The gcr.io/cloud-builders/mvn image doesn't contain the gcloud tools on which appengine:deploy depends so it doesn't work and I am forced to define a second "step" in the build to deploy.simon
Is it any particular guide or tutorial you are following? There is for example this community guide. Could you check if it also gives you an error?A.Queue
I found a list of supported builders and args: ['install'] is being used there with maven and in this example before ['package']. Have you tried it already?A.Queue
@A.Queue I managed to get things working, although I ended up having to build my own builder docker image to achieve it. The image contains gcloud openjdk8 and maven. I will post it below.simon

1 Answers

4
votes

In order to build a spring boot project and deploy it to google appengine using Google Cloud Build. I ended up having to first build a "builder" image using the image below and reference this image when performing my actual application builds.

Dockerfile

FROM debian:stretch
#
# Google Cloud SDK installation
# https://cloud.google.com/sdk/docs/quickstart-debian-ubuntu
RUN apt-get update -y && \
  apt-get install \
    apt-utils \
    dialog \
    gnupg \
    lsb-release \
    curl -y && \ 
  export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \
  echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
  curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
  apt-get update -y && \
  apt-get install google-cloud-sdk -y
# Install all available components
RUN apt-get install google-cloud-sdk \
  google-cloud-sdk \
  google-cloud-sdk-app-engine-go \
  google-cloud-sdk-app-engine-java \
  google-cloud-sdk-app-engine-python \
  google-cloud-sdk-app-engine-python-extras \
  google-cloud-sdk-bigtable-emulator \
  google-cloud-sdk-cbt \
  google-cloud-sdk-datastore-emulator \
  google-cloud-sdk-cloud-build-local \
  google-cloud-sdk-datalab \
  kubectl \
  google-cloud-sdk-pubsub-emulator -y
#
# OpenJDK installation
# https://linuxhint.com/install-openjdk-8-on-debian-9-stretch/
RUN apt-get install openjdk-8-jdk -y

#
# MAVEN installation
# https://github.com/carlossg/docker-maven/blob/f581ea002e5d067deb6213c00a4d217297cad469/jdk-8/Dockerfile
ARG MAVEN_VERSION=3.5.4
ARG USER_HOME_DIR="/root"
ARG SHA=ce50b1c91364cb77efe3776f756a6d92b76d9038b0a0782f7d53acf1e997a14d
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries

RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
  && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
  && echo "${SHA}  /tmp/apache-maven.tar.gz" | sha256sum -c - \
  && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
  && rm -f /tmp/apache-maven.tar.gz \
  && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn

ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"

WORKDIR /workspace

cloudbuild.yaml

# In this directory, run the following command to build this builder.
# $ gcloud builds submit . --config=cloudbuild.yaml

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '--tag=gcr.io/$PROJECT_ID/gcloud-maven', '.']
# Simple sanity check: invoke java to confirm that it was installed correctly.
- name: 'gcr.io/$PROJECT_ID/gcloud-maven'
  args: ['java', '-version']
# Simple sanity check: invoke gcloud to confirm that it was installed correctly.
- name: 'gcr.io/$PROJECT_ID/gcloud-maven'
  args: ['gcloud', 'projects', 'list']
# Simple sanity check: invoke maven to confirm that it was installed correctly.
- name: 'gcr.io/$PROJECT_ID/gcloud-maven'
  args: ['mvn', '--version']

images: ['gcr.io/$PROJECT_ID/gcloud-maven']

timeout: 1200s

My spring boot project's cloudbuild.yaml now references this image:

steps:
- name: 'gcr.io/$PROJECT_ID/gcloud-maven'
  args: ['mvn', 'appengine:deploy']

I will try to put this docker image on dockerhub and github for others to find. I will also appreciate people more familiar with docker and linux to help improve this image to reduce its size. (For example, use Alpine instead of Debian or Debian Stretch Slim). In the meantime, I hope this helps others like me.