From f7566d03755d6756789b491b4900f462b6e6db3c Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Thu, 18 Jul 2024 19:33:49 +0000 Subject: [PATCH] GH-5064: added docker makefile for Tomcat 9 / Jetty 9 and updated e2e tests Signed-off-by: Bart Hanssens --- docker/Dockerfile-jetty | 36 +++++++++++++ docker/{Dockerfile => Dockerfile-tomcat} | 4 +- docker/README.md | 18 ++++--- docker/build.sh | 53 ++++++++++--------- docker/docker-compose.yml | 9 ++-- docker/run.sh | 4 +- docker/shutdown.sh | 6 +++ docker/{ => tomcat}/web.xml | 0 e2e/run.sh | 50 +++++++++++------ pom.xml | 2 +- .../documentation/tools/server-workbench.md | 5 +- .../main/webapp/WEB-INF/views/overview.jsp | 2 +- 12 files changed, 130 insertions(+), 59 deletions(-) create mode 100644 docker/Dockerfile-jetty rename docker/{Dockerfile => Dockerfile-tomcat} (90%) create mode 100755 docker/shutdown.sh rename docker/{ => tomcat}/web.xml (100%) diff --git a/docker/Dockerfile-jetty b/docker/Dockerfile-jetty new file mode 100644 index 00000000000..b2f3e93d915 --- /dev/null +++ b/docker/Dockerfile-jetty @@ -0,0 +1,36 @@ +# Temp to reduce image size +FROM ubuntu:jammy AS temp + +RUN apt-get clean && apt-get update && apt-get install -y unzip + + +COPY ignore/rdf4j.zip /tmp/rdf4j.zip + +WORKDIR /tmp + +RUN unzip -q /tmp/rdf4j.zip + +# Final workbench +FROM jetty:9-jre17-eclipse-temurin +LABEL org.opencontainers.image.authors="Bart Hanssens (bart.hanssens@bosa.fgov.be)" + +USER root + +ENV JAVA_OPTIONS="-Dorg.eclipse.rdf4j.appdata.basedir=/var/rdf4j -Dorg.eclipse.rdf4j.rio.jsonld_secure_mode=false" +ENV JETTY_MODULES="server,bytebufferpool,threadpool,security,servlet,webapp,ext,plus,deploy,annotations,http,jsp,jstl" + +COPY --from=temp /tmp/eclipse-rdf4j*/war/*.war /var/lib/jetty/webapps/ + +# mimic Tomcat directories for data and logs + +RUN ln -s /usr/local/jetty/logs /var/lib/jetty/logs && \ + mkdir -p /usr/local/jetty/logs /var/rdf4j && \ + chown -R jetty:jetty /usr/local/jetty/logs && \ + chown -R jetty:jetty /var/rdf4j && \ + chown -R jetty:jetty /var/lib/jetty/webapps && \ + java -jar $JETTY_HOME/start.jar --add-to-start=$JETTY_MODULES --approve-all-licenses + +USER jetty + +EXPOSE 8080 + diff --git a/docker/Dockerfile b/docker/Dockerfile-tomcat similarity index 90% rename from docker/Dockerfile rename to docker/Dockerfile-tomcat index 800553f06f6..711e4f7681f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile-tomcat @@ -11,7 +11,7 @@ WORKDIR /tmp RUN unzip -q /tmp/rdf4j.zip # Final workbench -FROM tomcat:8.5-jre11-temurin +FROM tomcat:9-jre17-temurin-jammy MAINTAINER Bart Hanssens (bart.hanssens@bosa.fgov.be) RUN apt-get clean && apt-get update && apt-get upgrade -y && apt-get clean @@ -28,7 +28,7 @@ RUN rm -rf /usr/local/tomcat/webapps/* && \ COPY --from=temp /tmp/eclipse-rdf4j*/war/*.war /usr/local/tomcat/webapps/ -COPY web.xml /usr/local/tomcat/conf/web.xml +COPY tomcat/web.xml /usr/local/tomcat/conf/web.xml USER tomcat diff --git a/docker/README.md b/docker/README.md index 47178c7458a..8a96fa1332c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,8 +1,8 @@ # Eclipse RDF4J server and workbench -Docker image for RDF4J server and workbench, based on the Tomcat 8.5 (JRE 11) image. +Docker image for RDF4J server and workbench, based on a Tomcat 9.0 or Jetty 9.4 (JRE 17) image. -A slightly modified web.mxl is used to fix a known UTF-8 issue +A slightly modified web.mxl is used for Tomcat to fix a known UTF-8 issue (see also http://docs.rdf4j.org/server-workbench-console) ## Port @@ -12,7 +12,7 @@ By default port 8080 is exposed. ## Volumes * RDF4J data will be stored in `/var/rdf4j` - * Tomcat server logs in `/usr/local/tomcat/logs` + * Server logs go to `/usr/local/tomcat/logs` or `/usr/local/jetty/logs` ## Running the docker container @@ -20,21 +20,23 @@ The default java runtime options (-Xmx2g) can be changed by setting the `JAVA_OPTS` environment variable. To avoid data loss between restarts of the docker container, -the exposed volumes can be mapped to existing directories on the host. +the exposed volumes can be mapped to existing (and writable) directories on the host. Example: ``` docker run -d -p 127.0.0.1:8080:8080 -e JAVA_OPTS="-Xms1g -Xmx4g" \ - -v data:/var/rdf4j -v logs:/usr/local/tomcat/logs eclipse/rdf4j + -v /home/rdf4j/data:/var/rdf4j -v /home/rdf4j/logs:/usr/local/tomcat/logs \ + eclipse/rdf4j-workbench ``` -To access your server from another machine you will need to bind to `0.0.0.0` -instead of `127.0.0.1`. - The workbench will be accessible via http://localhost:8080/rdf4j-workbench The server will be accessible via http://localhost:8080/rdf4j-server + +In order to access the workbench and server from another machine, +you will need to bind the docker container to `0.0.0.0` instead of `127.0.0.1`. + ## Security Please note that the RDF4J server in the docker container is not diff --git a/docker/build.sh b/docker/build.sh index d9a7aa6daf2..d128c0661e1 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -5,45 +5,48 @@ set -e CURRENT=$(pwd) cd .. PROJECT_ROOT=$(pwd) +MVN_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml) + cd "$CURRENT" -# clean "ignore" directory -cd ignore -rm -f *.zip +if [ -z ${SKIP_BUILD+x} ]; then + # clean "ignore" directory + cd ignore + rm -f *.zip -cd "$PROJECT_ROOT" + cd "$PROJECT_ROOT" -# remove assembly/target since this is not removed by mvn clean -rm -rf assembly/target/ + # remove assembly/target since this is not removed by mvn clean + rm -rf assembly/target/ -MVN_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml) + #Clean, format and package + echo "Building with Maven" + mvn clean + mvn -T 2C formatter:format impsort:sort && mvn xml-format:xml-format + mvn install -DskipTests + mvn -Passembly package -DskipTests -Dmaven.javadoc.skip=true -Dformatter.skip=true -Dimpsort.skip=true -Dxml-format.skip=true -Djapicmp.skip -Denforcer.skip=true -Dbuildnumber.plugin.phase=none -Danimal.sniffer.skip=true -#Clean, format and package -echo "Building with Maven" -mvn clean -mvn -T 2C formatter:format impsort:sort && mvn xml-format:xml-format -mvn install -DskipTests -mvn -Passembly package -DskipTests -Dmaven.javadoc.skip=true -Dformatter.skip=true -Dimpsort.skip=true -Dxml-format.skip=true -Djapicmp.skip -Denforcer.skip=true -Dbuildnumber.plugin.phase=none -Danimal.sniffer.skip=true + # find .zip file + ZIP=$(find assembly/target/*.zip) + echo "$ZIP" -# find .zip file -ZIP=$(find assembly/target/*.zip) -echo "$ZIP" + # copy zip file into rdf4j.zip + cp "$ZIP" "${CURRENT}/ignore/rdf4j.zip" -# copy zip file into rdf4j.zip -cp "$ZIP" "${CURRENT}/ignore/rdf4j.zip" - -cd "$CURRENT" + cd "$CURRENT" +fi # build -echo "Building docker image" -docker compose build --pull --no-cache +APP_SERVER=${APP_SERVER:-tomcat} +echo "Building docker image for ${APP_SERVER}" -docker tag docker-rdf4j:latest eclipse/rdf4j-workbench:${MVN_VERSION} +docker compose build --pull --no-cache +docker tag docker-rdf4j:latest eclipse/rdf4j-workbench-${APP_SERVER}:${MVN_VERSION} echo " Docker image tagged as: - docker-rdf4j:latest - eclipse/rdf4j-workbench:${MVN_VERSION} + docker-rdf4j:latest + eclipse/rdf4j-workbench-${APP_SERVER}:${MVN_VERSION} To start the workbench and server: docker compose up -d diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 29fd5ddd6ed..63f5490cda4 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -3,14 +3,17 @@ services: rdf4j: environment: - APP_LOGGING_LEVEL=${APP_LOGGING_LEVEL} + - APP_SERVER=${APP_SERVER:-tomcat} ports: - 127.0.0.1:8080:8080 - build: . + build: + context: . + dockerfile: Dockerfile-${APP_SERVER:-tomcat} restart: always volumes: - rdf4j_data:/var/rdf4j - - rdf4j_logs:/usr/local/tomcat/logs + - rdf4j_logs:/usr/local/${APP_SERVER:-tomcat}/logs volumes: rdf4j_data: - rdf4j_logs: \ No newline at end of file + rdf4j_logs: diff --git a/docker/run.sh b/docker/run.sh index 1f7572be038..6cf1e75aff8 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -2,12 +2,12 @@ set -e ./build.sh -echo "Starting the docker container" +echo "Starting the docker container for ${APP_SERVER}" docker compose up --force-recreate -d # Wait for the server to be ready. Server is ready when the log contains something like "org.apache.catalina.startup.Catalina.start Server startup in 3400 ms". printf '%s' "Waiting for container to be ready" -while ! docker compose logs rdf4j | grep -q "Server startup in"; do +while ! docker compose logs rdf4j | grep -q -e "Server startup in" -e "Started ServerConnector"; do printf '%s' "." # Exit with error if we have looped 30 times (e.g. 30 seconds) ((c++)) && ((c == 30)) && echo "" && docker compose logs | tee && echo "" && docker ps -a | tee && printf '\n%s\n' "Timed out while waiting!" >&2 && exit 1 diff --git a/docker/shutdown.sh b/docker/shutdown.sh new file mode 100755 index 00000000000..adbdf22d585 --- /dev/null +++ b/docker/shutdown.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e + +echo "Stopping the docker container for ${APP_SERVER}" +docker compose down --rmi all -v + diff --git a/docker/web.xml b/docker/tomcat/web.xml similarity index 100% rename from docker/web.xml rename to docker/tomcat/web.xml diff --git a/e2e/run.sh b/e2e/run.sh index 130ed050b92..8fb93afce7e 100755 --- a/e2e/run.sh +++ b/e2e/run.sh @@ -12,23 +12,43 @@ set -e -cd .. -cd docker -./run.sh -./waitForDocker.sh -cd .. -cd e2e +for APP_SERVER in tomcat jetty; do + export APP_SERVER + + cd .. + cd docker + ./run.sh + ./waitForDocker.sh + cd .. + cd e2e -sleep 10 + sleep 10 -if [ ! -d 'node_modules' ]; then - echo "npm ci" - npm ci -fi + if [ ! -d 'node_modules' ]; then + echo "npm ci" + npm ci + fi -docker ps + docker ps -npx playwright install --with-deps # install browsers -npx playwright test -exit $? + npx playwright install --with-deps # install browsers + npx playwright test + + status_npx=$? + + cd .. + cd docker + ./shutdown.sh + + # test for error code + if [ $status_npx -ne 0 ] ; then + echo "Error in E2E test for $APP_SERVER" + exit $status_npx + fi + + echo "E2E test for $APP_SERVER OK" + + # don't redo the whole build process just for making another docker image + export SKIP_BUILD="skip" +done diff --git a/pom.xml b/pom.xml index 8338a334348..b878a558b14 100644 --- a/pom.xml +++ b/pom.xml @@ -374,7 +374,7 @@ 5.3.37 32.1.3-jre 1.37 - 3.1.0 + 4.0.0 5.9.3 9.4.54.v20240208 4.1.111.Final diff --git a/site/content/documentation/tools/server-workbench.md b/site/content/documentation/tools/server-workbench.md index 8994b859203..921c1780c73 100644 --- a/site/content/documentation/tools/server-workbench.md +++ b/site/content/documentation/tools/server-workbench.md @@ -15,13 +15,14 @@ RDF4J Server and RDF4J Workbench requires the following software: - Java 11 or newer - A Java Servlet Container that supports Java Servlet API 3.1 and Java Server Pages (JSP) 2.2, or newer. -We recommend using a recent, stable version of [Apache Tomcat](https://tomcat.apache.org/) ([version 9.0](https://tomcat.apache.org/download-90.cgi) at the time of writing). +We recommend using a recent, stable version of [Apache Tomcat](https://tomcat.apache.org/) (version 9.0) or [Jetty](https://jetty.org) (version 9.4) ## Deploying Server and Workbench RDF4J Server is a database management application: it provides HTTP access to RDF4J repositories, exposing them as SPARQL endpoints. RDF4J Server is meant to be accessed by other applications. Apart from some functionality to view the server’s log messages, it doesn’t provide any user oriented functionality. Instead, the user oriented functionality is part of RDF4J Workbench. The Workbench provides a web interface for querying, updating and exploring the repositories of an RDF4J Server. If you have not done so already, you will first need to [download the RDF4J SDK](/download). Both RDF4J Server and RDF4J Workbench can be found in the `war` directory of the SDK. The war-files in this directory need to be deployed in a Java Servlet Container. The deployment process is container-specific, please consult the documentation for your container on how to deploy a web application. For Apache Tomcat, we recommend using the [Tomcat Manager](https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html) to make deployment easier. +For Jetty, it's just a matter of copying the war-files to `$JETTY_BASE\webapps` After you have deployed the RDF4J Workbench webapp, you should be able to access it, by default, at path `http://localhost:8080/rdf4j-workbench`. You can point your browser at this location to verify that the deployment succeeded. @@ -440,7 +441,7 @@ For a list of supported features and more info on how to use SHACL - see [Progra ## Federation -NOTE: new in RDF4J 3.1 +NOTE: since RDF4J 3.1 RDF4J integrates federation support using the [FedX engine](/documentation/programming/federation/). diff --git a/tools/server/src/main/webapp/WEB-INF/views/overview.jsp b/tools/server/src/main/webapp/WEB-INF/views/overview.jsp index ceb7b95bfea..b31deafa835 100644 --- a/tools/server/src/main/webapp/WEB-INF/views/overview.jsp +++ b/tools/server/src/main/webapp/WEB-INF/views/overview.jsp @@ -1,2 +1,2 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> - \ No newline at end of file +