From 427538fa3babd6f2bafc811f8e3ba8462ed0774d Mon Sep 17 00:00:00 2001 From: vorachet Date: Sun, 26 Sep 2021 16:53:49 +0700 Subject: [PATCH] tested --- .gitignore | 5 ++ Dockerfile | 121 +++++++++++++++++++++++++++++++++++++ FUSEKI_COMMANDS.md | 38 ++++++++++++ README.md | 30 ++++++++- docker-compose.yml | 18 ++++++ download.sh | 147 +++++++++++++++++++++++++++++++++++++++++++++ entrypoint.sh | 5 ++ log4j2.properties | 70 +++++++++++++++++++++ 8 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 FUSEKI_COMMANDS.md create mode 100644 docker-compose.yml create mode 100644 download.sh create mode 100644 entrypoint.sh create mode 100644 log4j2.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a99b19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +databases +logs +public +security +readonly \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3cad8e5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,121 @@ +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. + +## Apache Jena Fuseki server Dockerfile. + +## This Dockefile builds a reduced footprint container. + +ARG OPENJDK_VERSION=15 +ARG ALPINE_VERSION=3.12 +ARG JENA_VERSION=4.2.0 + +# Internal, passed between stages. +ARG FUSEKI_DIR=/fuseki +ARG FUSEKI_JAR=jena-fuseki-server-${JENA_VERSION}.jar +ARG JAVA_MINIMAL=/opt/java-minimal + +## ---- Stage: Download and build java. +FROM openjdk:${OPENJDK_VERSION}-alpine AS base + +ARG JAVA_MINIMAL +ARG JENA_VERSION +ARG FUSEKI_DIR +ARG FUSEKI_JAR +ARG REPO=https://repo1.maven.org/maven2 +ARG JAR_URL=${REPO}/org/apache/jena/jena-fuseki-server/${JENA_VERSION}/${FUSEKI_JAR} + +RUN [ "${JENA_VERSION}" != "" ] || { echo -e '\n**** Set JENA_VERSION ****\n' ; exit 1 ; } +RUN echo && echo "==== Docker build for Apache Jena Fuseki ${JENA_VERSION} ====" && echo + +# Alpine: For objcopy used in jlink +RUN rm -rf /var/cache/apk/* && \ + rm -rf /tmp/* + +RUN echo -e "http://nl.alpinelinux.org/alpine/v3.5/main\nhttp://nl.alpinelinux.org/alpine/v3.5/community" > /etc/apk/repositories +RUN apk add --no-cache curl binutils + +## -- Fuseki installed and runs in /fuseki. +WORKDIR $FUSEKI_DIR + +## -- Download the jar file. +COPY download.sh . +RUN chmod a+x download.sh + +# Download, with check of the SHA1 checksum. +RUN ./download.sh --chksum sha1 "$JAR_URL" + +## -- Alternatives to download : copy already downloaded. +## COPY ${FUSEKI_JAR} . + +## Use Docker ADD - does not retry, does not check checksum, and may run every build. +## ADD "$JAR_URL" + +## -- Make reduced Java JDK + +ARG JDEPS_EXTRA="jdk.crypto.cryptoki,jdk.crypto.ec" +RUN \ + JDEPS="$(jdeps --multi-release base --print-module-deps --ignore-missing-deps ${FUSEKI_JAR})" && \ + jlink \ + --compress 2 --strip-debug --no-header-files --no-man-pages \ + --output "${JAVA_MINIMAL}" \ + --add-modules "${JDEPS},${JDEPS_EXTRA}" + +ADD entrypoint.sh . +ADD log4j2.properties . + +# Run as this user +# -H : no home directorry +# -D : no password + +RUN adduser -H -D fuseki fuseki + +## ---- Stage: Build runtime +FROM alpine:${ALPINE_VERSION} + +## Import ARGs +ARG JENA_VERSION +ARG JAVA_MINIMAL +ARG FUSEKI_DIR +ARG FUSEKI_JAR + +COPY --from=base /opt/java-minimal /opt/java-minimal +COPY --from=base /fuseki /fuseki +COPY --from=base /etc/passwd /etc/passwd + +WORKDIR $FUSEKI_DIR + +ARG LOGS=${FUSEKI_DIR}/logs +ARG DATA=${FUSEKI_DIR}/databases + +RUN \ + mkdir -p $LOGS && \ + mkdir -p $DATA && \ + chown -R fuseki ${FUSEKI_DIR} && \ + chmod a+x entrypoint.sh + +## Default environment variables. +ENV \ + JAVA_HOME=${JAVA_MINIMAL} \ + JAVA_OPTIONS="-Xmx2048m -Xms2048m" \ + JENA_VERSION=${JENA_VERSION} \ + FUSEKI_JAR="${FUSEKI_JAR}" \ + FUSEKI_DIR="${FUSEKI_DIR}" + +USER fuseki + +EXPOSE 3030 + +ENTRYPOINT ["./entrypoint.sh" ] +CMD [] diff --git a/FUSEKI_COMMANDS.md b/FUSEKI_COMMANDS.md new file mode 100644 index 0000000..34e9882 --- /dev/null +++ b/FUSEKI_COMMANDS.md @@ -0,0 +1,38 @@ +``` +fuseki [--config=FILE] [--mem|--desc=AssemblerFile|--file=FILE] [--port PORT] /DatasetPathName + Fuseki Main + --mem Create an in-memory, non-persistent dataset for the server + --file=FILE Create an in-memory, non-persistent dataset for the server, initialised with the contents of the file + --tdb2 Use TDB2 for command line persistent datasets (dfault is TDB1) + --loc=DIR Use an existing TDB database (or create if does not exist) + --memTDB Create an in-memory, non-persistent dataset using TDB (testing only) + --config= Use a configuration file to determine the services + --desc= Assembler description file + --port Listen on this port number + --localhost Listen only on the localhost interface + --timeout= Global timeout applied to queries (value in ms) -- format is X[,Y] + --update Allow updates (via SPARQL Update and SPARQL HTTP Update) + --gzip=on|off Enable GZip compression (HTTP Accept-Encoding) if request header set + --base=DIR Directory for static content + --sparqler=DIR Run with SPARQLer services Directory for static content + --validators Install validators + --general=PATH Add a general SPARQL endpoint (without a dataset) at /PATH + --auth=[basic|Digest] Run the server using basic or digest authentication (dft: digest). + --https=CONF https certificate access details. JSON file { "cert":FILE , "passwd"; SECRET } + --httpsPort=NUM https port (default port is 3043) + --passwd=FILE Password file + --cors Enable CORS + --ping Enable /$/ping + --stats Enable /$/stats + Symbol definition + --set Set a configuration symbol to a value + General + -v --verbose Verbose + -q --quiet Run with minimal output + --debug Output information for debugging + --help + --version Version information + --strict Operate in strict SPARQL mode (no extensions of any kind) +/fuseki $ + +``` \ No newline at end of file diff --git a/README.md b/README.md index 7e59600..dfd705e 100644 --- a/README.md +++ b/README.md @@ -1 +1,29 @@ -# README +# Fuseki2 Docker Installation + +This project is based the offical FUSEKI documentation on https://jena.apache.org/documentation/fuseki2/fuseki-docker.html + +For DevOps who gonna build your own Fuseki2 docker image, this repo provides another documentation on this task. + + +# Fixed build variables + +``` +ARG OPENJDK_VERSION=15 +ARG ALPINE_VERSION=3.12 +ARG JENA_VERSION=4.2.0 +``` + +# Fixed broken alpinelinux APK + +The following command has been added to Docker for solving broken APK repo issue +``` +RUN echo -e "http://nl.alpinelinux.org/alpine/v3.5/main\nhttp://nl.alpinelinux.org/alpine/v3.5/community" > /etc/apk/repositories + +``` +# Build image + +``` +$ docker-compose build +``` + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9644605 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +# Modified by Vorachet + +version: '3.0' +services: + fuseki: + build: + context: . + dockerfile: Dockerfile + image: fuseki + ports: + - "3030:3030" + - "3043:3043" + volumes: + - ./logs:/fuseki/logs + - ./public:/fuseki/public + - ./security:/fuseki/security + - ./readonly:/fuseki/readonly + - ./databases:/fuseki/databases diff --git a/download.sh b/download.sh new file mode 100644 index 0000000..bf4e2ae --- /dev/null +++ b/download.sh @@ -0,0 +1,147 @@ +#!/bin/sh + +## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is an ash/dash script (it uses "local"), not a bash script. +# It can run in an Alpine image durign a docker build. +# +# The advantage over using docker ADD is that it checks +# whether download file is already present and does not +# download each time. +# +# Shell script to download URL and check the checksum + +USAGE="Usage: $(basename "$0") --chksum [sha1|sha512] URL" + +if [ $# -eq 0 ] +then + echo "$USAGE" 2>&1 + exit 1 +fi + +CHKSUM_TYPE='unset' + +while [ $# -gt 0 ] ; do + case "$1" in + --chksum|-chksum|-sha|--sha) + if [ $# -lt 2 ] + then + echo "$USAGE" 1>&2 + exit 1 + fi + CHKSUM_TYPE=$2 + shift + shift + ;; + -h|--help) + echo "$USAGE" 1>&2 + exit 0 + ;; + -*) + echo "$USAGE" 1>&2 + exit 1 + ;; + *) + if [ $# -ne 1 ] + then + echo "$USAGE" 1>&2 + exit 1 + fi + URL="$1" + shift + ;; + esac +done + +case "${CHKSUM_TYPE}" in + unset) + echo "$USAGE" 1>&2 + exit 1 + ;; + sha*|md5) ;; + *) + echo "Bad checksum type: '$CHKSUM_TYPE' (must start 'sha' or be 'md5')" 2>&1 + exit 1 + ;; +esac + +## ---- Script starts ---- + +ARTIFACT_URL="${URL}" +ARTIFACT_NAME="$(basename "$ARTIFACT_URL")" + +# -------- Checksum details + +CHKSUM_EXT=".${CHKSUM_TYPE}" +CHKSUM_URL="${ARTIFACT_URL}${CHKSUM_EXT}" +CHKSUM_FILE="${ARTIFACT_NAME}${CHKSUM_EXT}" +CHKSUMPROG="${CHKSUM_TYPE}sum" +# -------- + +CURL_FETCH_OPTS="-s -S --fail --location --max-redirs 3" +if false +then + echo "ARTIFACT_URL=$ARTIFACT_URL" + echo "CHKSUM_URL=$CHKSUM_URL" +fi + +download() { # URL + local URL="$1" + local FN="$(basename "$URL")" + if [ ! -e "$FN" ] + then + echo "Fetching $URL" + curl $CURL_FETCH_OPTS "$URL" --output "$FN" \ + || { echo "Bad download of $FN" 2>&1 ; return 1 ; } + else + echo "$FN already present" + fi + return 0 +} + +checkChksum() { # Filename checksum + local FN="$1" + local CHKSUM="$2" + if [ ! -e "$FN" ] + then + echo "No such file: '$FN'" 2>&1 + exit 1 + fi + # NB Two spaces required for busybox + echo "$CHKSUM $FN" | ${CHKSUMPROG} -c > /dev/null +} + +download "$ARTIFACT_URL" || exit 1 + +if [ -z "$CHKSUM" ] +then + # Checksum not previously set. + # Extract from file, copes with variations in content (filename or not) + download "$CHKSUM_URL" || exit 1 + CHKSUM="$(cut -d' ' -f1 "$CHKSUM_FILE")" +fi + +checkChksum "${ARTIFACT_NAME}" "$CHKSUM" +if [ $? = 0 ] +then + echo "Good download: $ARTIFACT_NAME" +else + echo "BAD download !!!! $ARTIFACT_NAME" + echo "To retry: delete downloaded files and try again" + exit 1 +fi diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..a4ab8cd --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/sh +## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0 + +## env | sort +exec "$JAVA_HOME/bin/java" $JAVA_OPTIONS -jar "${FUSEKI_DIR}/${FUSEKI_JAR}" "$@" diff --git a/log4j2.properties b/log4j2.properties new file mode 100644 index 0000000..e376544 --- /dev/null +++ b/log4j2.properties @@ -0,0 +1,70 @@ +## Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0 +status = error +name = PropertiesConfig + +## filters = threshold +## filter.threshold.type = ThresholdFilter +## filter.threshold.level = ALL + +appender.console.type = Console +appender.console.name = OUT +appender.console.target = SYSTEM_OUT +appender.console.layout.type = PatternLayout +## appender.console.layout.pattern = %d{HH:mm:ss} %-5p %-15c{1} :: %m%n +## Include date. +appender.console.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n + +## To a file. +## appender.file.type = File +## appender.file.name = FILE +## appender.file.fileName=/fuseki/logs/log.fuseki +## appender.file.layout.type=PatternLayout +## appender.file.layout.pattern = [%d{yyyy-MM-dd HH:mm:ss}] %-5p %-15c{1} :: %m%n + +rootLogger.level = INFO +rootLogger.appenderRef.stdout.ref = OUT + +logger.jena.name = org.apache.jena +logger.jena.level = INFO + +logger.arq-exec.name = org.apache.jena.arq.exec +logger.arq-exec.level = INFO + +logger.riot.name = org.apache.jena.riot +logger.riot.level = INFO + +logger.fuseki.name = org.apache.jena.fuseki +logger.fuseki.level = INFO + +logger.fuseki-fuseki.name = org.apache.jena.fuseki.Fuseki +logger.fuseki-fuseki.level = INFO + +logger.fuseki-server.name = org.apache.jena.fuseki.Server +logger.fuseki-server.level = INFO + +logger.fuseki-admin.name = org.apache.jena.fuseki.Admin +logger.fuseki-admin.level = INFO + +logger.jetty.name = org.eclipse.jetty +logger.jetty.level = WARN + +# May be useful to turn up to DEBUG if debugging HTTP communication issues +logger.apache-http.name = org.apache.http +logger.apache-http.level = WARN + +logger.shiro.name = org.apache.shiro +logger.shiro.level = WARN +# Hide bug in Shiro 1.5.x +logger.shiro-realm.name = org.apache.shiro.realm.text.IniRealm +logger.shiro-realm.level = ERROR + +# This goes out in NCSA format +appender.plain.type = Console +appender.plain.name = PLAIN +appender.plain.layout.type = PatternLayout +appender.plain.layout.pattern = %m%n + +logger.request-log.name = org.apache.jena.fuseki.Request +logger.request-log.additivity = false +logger.request-log.level = OFF +logger.request-log.appenderRef.plain.ref = PLAIN