From 9af9eb4182be2219e4ade09afc3564d7d231b947 Mon Sep 17 00:00:00 2001 From: germaine Date: Fri, 17 Nov 2023 23:59:37 +0100 Subject: [PATCH 1/9] Starting dockerization. --- Dockerfile | 34 +++++++++++++++++++++++++++ build.sh | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Dockerfile create mode 100644 build.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b0343cd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +FROM openjdk:17-bullseye + +ARG SERVER_NAME_DEFAULT=wapserver + +#This is the post that you want to use on the HOST machine, not in the container itself +ARG PORT_DEFAULT=8090 +ARG HOST_DEFAULT=localhost +ARG ROOT_DIRECTORY_DEFAULT=/spring + +# Install git as additional requirement +RUN apt-get -y update && \ + apt-get -y upgrade && \ + apt-get install -y --no-install-recommends git bash && \ + apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +ENV SERVICE_DIRECTORY=${ROOT_DIRECTORY_DEFAULT}/${SERVER_NAME_DEFAULT} +RUN mkdir -p /git +WORKDIR /git +COPY . . +# Build service in given directory +RUN echo $SERVICE_DIRECTORY +RUN bash ./build.sh $SERVICE_DIRECTORY + +#You can use this to set config variables or mount in an application.properties file +ENV SPRING_APPLICATION_JSON "{\"WapPort\": ${PORT_DEFAULT}, \"Hostname\": ${HOST_DEFAULT}}" + +EXPOSE ${PORT_DEFAULT} +WORKDIR $SERVICE_DIRECTORY +COPY ./profiles ./profiles/ +COPY ./schemas ./schemas/ +COPY ./webcontent ./webcontent/ +COPY ./doc ./doc/ +ENTRYPOINT ["/spring/wapserver/run.sh"] \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..bc180c2 --- /dev/null +++ b/build.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Check no of parameters. +if [ "$#" -ne 1 ]; then + echo "Illegal number of parameters!" + usage +fi + +INSTALLATION_DIRECTORY=$1 +ACTUAL_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Check if directory exists + if [ ! -d "$INSTALLATION_DIRECTORY" ]; then + # Create directory if it doesn't exists. + mkdir -p "$INSTALLATION_DIRECTORY" + if [ $? -ne 0 ]; then + echo "Error creating directory '$INSTALLATION_DIRECTORY'!" + echo "Please make sure that you have the correct access permissions for the specified directory." + exit 1 + fi + fi + # Check if directory is empty + if [ ! -z "$(ls -A "$INSTALLATION_DIRECTORY")" ]; then + echo "Directory '$INSTALLATION_DIRECTORY' is not empty!" + echo "Please enter an empty or a new directory!" + exit 1 + fi + # Convert variable of installation directory to an absolute path + cd "$INSTALLATION_DIRECTORY" + INSTALLATION_DIRECTORY=`pwd` + cd "$ACTUAL_DIR" + +APP_NAME=`./gradlew -q printProjectName` +APP_NAME=${APP_NAME##*$'\n'} +echo "$APP_NAME" + +echo Build service... +./gradlew -Dprofile=minimal clean build + +echo "Copy jar file to '$INSTALLATION_DIRECTORY'..." +find . -name "$APP_NAME.jar" -exec cp '{}' "$INSTALLATION_DIRECTORY" \; + +# Create run script +echo "$INSTALLATION_DIRECTORY" +cd "$INSTALLATION_DIRECTORY" + +# Determine name of jar file. +jarFile=(`ls $APP_NAME.jar`) + +java -jar $jarFile "--create-config" + +echo '#!/bin/sh' >> run.sh +echo 'pwd' >> run.sh +echo 'ls' >> run.sh +echo 'cat run.sh' >> run.sh +echo "################################################################################" >> run.sh +echo "# Define jar file" >> run.sh +echo "################################################################################" >> run.sh +echo jarFile=$jarFile >> run.sh +echo " " >> run.sh +echo "################################################################################" >> run.sh +echo "# Start micro service" >> run.sh +echo "################################################################################" >> run.sh +echo 'java -jar $jarFile' >> run.sh + +# make script executable +chmod 755 run.sh \ No newline at end of file From ccd83108040e2d9283f31fee69b4aef41fa96d54 Mon Sep 17 00:00:00 2001 From: germaine Date: Sat, 18 Nov 2023 01:34:46 +0100 Subject: [PATCH 2/9] Fixes on dockerfile --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b0343cd..ef1ece9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ ARG SERVER_NAME_DEFAULT=wapserver #This is the post that you want to use on the HOST machine, not in the container itself ARG PORT_DEFAULT=8090 +ARG SPARQ_DEFAULT=3330 ARG HOST_DEFAULT=localhost ARG ROOT_DIRECTORY_DEFAULT=/spring @@ -23,9 +24,10 @@ RUN echo $SERVICE_DIRECTORY RUN bash ./build.sh $SERVICE_DIRECTORY #You can use this to set config variables or mount in an application.properties file -ENV SPRING_APPLICATION_JSON "{\"WapPort\": ${PORT_DEFAULT}, \"Hostname\": ${HOST_DEFAULT}}" +ENV SPRING_APPLICATION_JSON "{\"WapPort\": ${PORT_DEFAULT}, \"Hostname\": \"${HOST_DEFAULT}\"}" EXPOSE ${PORT_DEFAULT} +EXPOSE ${SPARQL_DEFAULT} WORKDIR $SERVICE_DIRECTORY COPY ./profiles ./profiles/ COPY ./schemas ./schemas/ From 6a29c63af6264a18b2d8e35b7122ea5ba02b94b5 Mon Sep 17 00:00:00 2001 From: germaine Date: Tue, 19 Mar 2024 18:25:06 +0100 Subject: [PATCH 3/9] Moved Dockerfile to subfolder Updated base image added dockerignore file [skip ci] --- .dockerignore | 17 +++++++++++++++++ Dockerfile => docker/Dockerfile | 13 ++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 .dockerignore rename Dockerfile => docker/Dockerfile (86%) diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2aceab5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +#git +.git +.gitattributes +.gitignore +.github/ +#IDE +.idea +#build +.gradle/ +build +#data +production_db +#misc +CHANGELOG +LICENSE +temp +docker diff --git a/Dockerfile b/docker/Dockerfile similarity index 86% rename from Dockerfile rename to docker/Dockerfile index ef1ece9..b2c0497 100644 --- a/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,4 @@ -FROM openjdk:17-bullseye - +FROM eclipse-temurin:17-jdk ARG SERVER_NAME_DEFAULT=wapserver #This is the post that you want to use on the HOST machine, not in the container itself @@ -18,7 +17,7 @@ RUN apt-get -y update && \ ENV SERVICE_DIRECTORY=${ROOT_DIRECTORY_DEFAULT}/${SERVER_NAME_DEFAULT} RUN mkdir -p /git WORKDIR /git -COPY . . +COPY .. . # Build service in given directory RUN echo $SERVICE_DIRECTORY RUN bash ./build.sh $SERVICE_DIRECTORY @@ -29,8 +28,8 @@ ENV SPRING_APPLICATION_JSON "{\"WapPort\": ${PORT_DEFAULT}, \"Hostname\": \"${HO EXPOSE ${PORT_DEFAULT} EXPOSE ${SPARQL_DEFAULT} WORKDIR $SERVICE_DIRECTORY -COPY ./profiles ./profiles/ -COPY ./schemas ./schemas/ -COPY ./webcontent ./webcontent/ -COPY ./doc ./doc/ +COPY ../profiles ./profiles/ +COPY ../schemas ./schemas/ +COPY ../webcontent ./webcontent/ +COPY ../doc ./doc/ ENTRYPOINT ["/spring/wapserver/run.sh"] \ No newline at end of file From 8fe78d3c9840a58a139489f357e6ca48b7d67afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germaine=20G=C3=B6tzelmann?= Date: Wed, 10 Dec 2025 19:20:10 +0100 Subject: [PATCH 4/9] align docker default port with application default port --- docker/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b2c0497..84b0c56 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,8 +1,7 @@ FROM eclipse-temurin:17-jdk ARG SERVER_NAME_DEFAULT=wapserver -#This is the post that you want to use on the HOST machine, not in the container itself -ARG PORT_DEFAULT=8090 +ARG PORT_DEFAULT=8080 ARG SPARQ_DEFAULT=3330 ARG HOST_DEFAULT=localhost ARG ROOT_DIRECTORY_DEFAULT=/spring From a5e64a3915488dd5524ed0e71885a1ce4c893b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germaine=20G=C3=B6tzelmann?= Date: Wed, 10 Dec 2025 21:26:24 +0100 Subject: [PATCH 5/9] Readme updated for docker usage --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fa2585..29fb166 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,21 @@ This project contains a server for creating and managing annotations based on th the complete Web Annotation Protocol (WAP). The service is realized as microservice using Spring Boot and can be operated standalone. -## How to build +## How to build and use + +### Docker + +``` +docker build -f docker/Dockerfile -t wap-server . +``` + +To run the application at `http://localhost:`, use: + +``` +docker run -d -p :8080 -e WAPBASEPATH=http://localhost: wap-server +``` + +### From source To install the application from source, see [howtos](howtos/summary.md). From 7abc2fa41d3a17c7ef6bce9366ae482a28d946a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germaine=20G=C3=B6tzelmann?= Date: Wed, 10 Dec 2025 21:33:04 +0100 Subject: [PATCH 6/9] Workflow for docker test (same as bootjar test) --- .github/workflows/docker_testing.yml | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/docker_testing.yml diff --git a/.github/workflows/docker_testing.yml b/.github/workflows/docker_testing.yml new file mode 100644 index 0000000..7bc9095 --- /dev/null +++ b/.github/workflows/docker_testing.yml @@ -0,0 +1,72 @@ +name: Build and Test Dockerized App + +on: + push: + pull_request: + branches: [ main, development ] + +jobs: + build-and-test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + java: [17, 21] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: ${{ matrix.java }} + + - name: Grant execute permission for Gradle wrapper (Unix) + if: runner.os != 'Windows' + run: chmod +x gradlew + + # Build Docker image instead of bootable JAR + - name: Build Docker image + run: | + docker build -f docker/Dockerfile -t wap-server:${{ matrix.os }}-${{ matrix.java }} . + + # Run Docker container (detached, expose port 8080) + - name: Run Docker container + run: | + docker run -d -p 8080:8080 --name wap-server \ + wap-server:${{ matrix.os }}-${{ matrix.java }} + sleep 100 # Give the server time to start + + - name: hurl install + uses: gacts/install-hurl@v1.3.0 + with: {disable-cache: true} + + - name: hurl CRUD tests (windows) + if: runner.os == 'Windows' + shell: bash + run: | + for file in ./integration_tests/CRUD/*.hurl; do + hurl --variable host=http://localhost:8080 --test "$file" --verbose --error-format=long --continue-on-error --report-html hurlreports + done + + - name: hurl tests (other) + if: runner.os != 'Windows' + run: hurl --variable host=http://localhost:8080 --test ./integration_tests/CRUD/*.hurl --verbose --error-format=long --continue-on-error --report-html hurlreports + + # Stop and clean up container + - name: Stop Docker container + if: always() + run: | + docker logs wap-server + docker stop wap-server + docker rm wap-server + + # Upload artifacts (optional: you may want to upload Docker logs instead of JARs) + - name: Upload Docker logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: docker_logs_jdk${{ matrix.java }}_${{ matrix.os }} + path: ./hurlreports From ae19dd9c58aaa39129b264759bfe812365de558c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germaine=20G=C3=B6tzelmann?= Date: Wed, 10 Dec 2025 21:45:45 +0100 Subject: [PATCH 7/9] Workflow: check docker startup more transparently --- .github/workflows/docker_testing.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker_testing.yml b/.github/workflows/docker_testing.yml index 7bc9095..776904a 100644 --- a/.github/workflows/docker_testing.yml +++ b/.github/workflows/docker_testing.yml @@ -37,7 +37,21 @@ jobs: run: | docker run -d -p 8080:8080 --name wap-server \ wap-server:${{ matrix.os }}-${{ matrix.java }} - sleep 100 # Give the server time to start + echo "Wait for wap server to be healthy before proceeding to tests" + while true; do + docker ps -a + if ! docker ps | grep -q wap-server; then + echo "Docker container stopped unexpectedly. Aborting." + exit 1 + fi + if curl -f http://localhost:8080; then + echo "Service is running." + break + fi + echo "Waiting for the service to be ready..." + docker logs --tail 20 wap-server + sleep 5 + done - name: hurl install uses: gacts/install-hurl@v1.3.0 From e223141aa2960fdf9a0957f12145c30014d1c927 Mon Sep 17 00:00:00 2001 From: germaine Date: Fri, 5 Apr 2024 11:41:07 +0200 Subject: [PATCH 8/9] exclude linter from printProjectName task --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 8e45f92..66dbd63 100644 --- a/build.gradle +++ b/build.gradle @@ -188,3 +188,7 @@ tasks.register('printProjectName') { println "${project.name}" } } + +gradleLint { + skipForTask('printProjectName') +} From 724edc2d29c3dc1f0fa0c8fa49bb17f710c8e6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germaine=20G=C3=B6tzelmann?= Date: Wed, 10 Dec 2025 22:43:05 +0100 Subject: [PATCH 9/9] workflow for docker publish --- .github/workflows/docker_publish.yml | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/docker_publish.yml diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml new file mode 100644 index 0000000..5e6d616 --- /dev/null +++ b/.github/workflows/docker_publish.yml @@ -0,0 +1,54 @@ +name: Create and publish a Docker image + +# Configures this workflow to run every time a change is pushed to the branch called `release`. +on: + push: + branches: ['main'] + +# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: ./docker + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + + # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true \ No newline at end of file