diff --git a/.gitignore b/.gitignore index 0d6af92..d392e59 100644 --- a/.gitignore +++ b/.gitignore @@ -251,4 +251,6 @@ $RECYCLE.BIN/ # and uncomment the following lines # .pnp.* -# End of https://www.toptal.com/developers/gitignore/api/macos,windows,linux,node,deno,dotenv,astro,yarn \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/macos,windows,linux,node,deno,dotenv,astro,yarn + +infra/qlever/output \ No newline at end of file diff --git a/infra/qlever/Dockerfile b/infra/qlever/Dockerfile deleted file mode 100644 index ce429b3..0000000 --- a/infra/qlever/Dockerfile +++ /dev/null @@ -1,128 +0,0 @@ -# docker/server.Dockerfile - -# ----------------------------- -# Stage 1: Build QLever from source -# ----------------------------- -FROM ubuntu:24.04 AS qlever-build - -ARG QLEVER_GIT_REF="master" # You can pin to a tag/commit if you want -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update \ - && apt-get install -y \ - git \ - cmake \ - ninja-build \ - build-essential \ - libzstd-dev \ - libjemalloc-dev \ - libboost-all-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /src - -# Clone QLever and checkout the requested ref -RUN git clone https://github.com/ad-freiburg/qlever.git . \ - && git checkout "${QLEVER_GIT_REF}" - -# Configure with conservative CPU flags so we don't hit Illegal Instruction -RUN cmake -S . -B build -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_FLAGS="-march=x86-64 -mtune=generic" \ - -DUSE_PARALLEL=true - -# Build only the two main binaries we need -RUN cmake --build build --target IndexBuilderMain ServerMain -j4 - -# ----------------------------- -# Stage 2: Stop-on-call helper -# ----------------------------- -FROM ghcr.io/ludovicm67/stop-on-call:v0.1.0 AS soc - -# ----------------------------- -# Stage 3: Final QLever runtime image -# ----------------------------- -FROM ubuntu:24.04 - -# Match the CLI version to something recent / stable -# Check PyPI for latest: https://pypi.org/project/qlever/ -ARG QLEVER_VERSION="0.5.35" -ARG PIPX_VERSION="1.8.0" - -ENV DEBIAN_FRONTEND=noninteractive - -# Core runtime deps for QLever binaries + Python CLI -RUN apt-get update \ - && apt-get upgrade -y \ - && apt-get install -y \ - bash-completion \ - bzip2 \ - curl \ - libboost-iostreams1.83.0 \ - libboost-program-options1.83.0 \ - libboost-url1.83.0 \ - libgomp1 \ - libicu74 \ - libjemalloc2 \ - libzstd1 \ - pipx \ - python3 \ - unzip \ - uuid-runtime \ - vim \ - wget \ - && apt-get autoremove -y \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Create dirs and relax permissions so the `nobody`-like user can write -RUN mkdir -p /qlever /data \ - && chmod -R a+rw /data \ - && chmod -R a+rw /qlever - -# Shell convenience for interactive use (optional, but nice) -RUN echo 'eval "$(register-python-argcomplete qlever)"' >> /etc/bash.bashrc \ - && echo 'PATH="/qlever:${PATH}"' >> /etc/bash.bashrc - -ENV QLEVER_ARGCOMPLETE_ENABLED="1" -ENV QLEVER_IS_RUNNING_IN_CONTAINER="1" - -# Upgrade pipx to the pyz version with --global support -RUN curl -L -o /usr/local/bin/pipx "https://github.com/pypa/pipx/releases/download/${PIPX_VERSION}/pipx.pyz" \ - && chmod +x /usr/local/bin/pipx - -# Install the QLever CLI (Python wrapper); this will invoke our compiled binaries -RUN pipx install --global "qlever==${QLEVER_VERSION}" - -# Copy compiled binaries from the build stage -# NOTE: CMake by default puts executables directly in build/, not under apps/ -COPY --from=qlever-build /src/build/IndexBuilderMain /qlever/ -COPY --from=qlever-build /src/build/ServerMain /qlever/ - -ENV PATH="/qlever:${PATH}" - -# Copy your helper scripts -RUN mkdir -p /qlever/scripts -COPY ./scripts/generate-qleverfile.sh /qlever/scripts/ -COPY ./scripts/entrypoint.sh /qlever/scripts/ -RUN chmod +x /qlever/scripts/*.sh - -# Configure Stop On Call -ENV STOP_ON_CALL_ENABLED="false" -COPY --from=soc /app/stop_on_call /usr/bin/stop_on_call - -# Use the nobody user by default (65534) -USER 65534 - -WORKDIR /qlever - -EXPOSE 7001 - -# Default envs (these are also used by generate-qleverfile.sh) -ENV QLEVER_SERVER_HOST_NAME="127.0.0.1" -ENV QLEVER_SERVER_PORT="7001" -ENV QLEVER_RUNTIME_SYSTEM="native" - -# We let the script be the main process; keep ENTRYPOINT empty for compatibility -ENTRYPOINT [ "" ] -CMD [ "/qlever/scripts/entrypoint.sh" ] diff --git a/infra/qlever/docker-compose.yaml b/infra/qlever/docker-compose.yaml index a75af82..7fd8618 100644 --- a/infra/qlever/docker-compose.yaml +++ b/infra/qlever/docker-compose.yaml @@ -1,28 +1,46 @@ services: - # One-shot init container to fix permissions on the data volume - qlever-init: - image: busybox:latest - container_name: qlever-init - command: ["sh", "-c", "chown -R 65534:0 /data"] - volumes: - - ./qlever-data:/data - restart: "no" - qlever-server: - build: - context: . - dockerfile: ./Dockerfile - image: local/qlever-server:latest + image: adfreiburg/qlever:latest container_name: qlever-server - user: "65534:0" # run as 'nobody' (uid 65534), group root - depends_on: - - qlever-init # make sure perms are fixed first + + # M1 fix: you already proved amd64 works for indexing + platform: linux/amd64 + + # Not strictly required because your entrypoint does `cd /data`, + # but it keeps everything consistent and avoids surprises. + working_dir: /data + env_file: - - ./qlever.env # QLever + indexing config (see below) + - ./qlever.env + volumes: - - ./qlever-data:/data # QLever index + Qleverfile live here - - ./data/data.nt:/data/data.nt:ro # your RDF data file + # QLever working dir (Qleverfile + index artifacts) + - ./output:/data + + # Your raw host data folder, mounted read-only + - ./data:/input:ro + + # Your scripts + - ./scripts:/qlever/scripts:ro + + # Override the image entrypoint completely + entrypoint: ["/bin/bash", "/qlever/scripts/entrypoint.sh"] + + ports: + - "7001:7001" # server + + restart: unless-stopped + + qlever-ui: + image: adfreiburg/qlever-ui:latest + container_name: qlever-ui + depends_on: + - qlever-server ports: - - "7001:7001" # SPARQL endpoint - stop_grace_period: 0s + - "7002:7000" restart: unless-stopped + volumes: + - qlever-ui-db:/app/db + +volumes: + qlever-ui-db: diff --git a/infra/qlever/qlever.env b/infra/qlever/qlever.env index d195ef5..eade80d 100644 --- a/infra/qlever/qlever.env +++ b/infra/qlever/qlever.env @@ -6,11 +6,12 @@ QLEVER_DATA_NAME=local QLEVER_DATA_DESCRIPTION=Local NT dataset for QLever # [index] -QLEVER_INDEX_INPUT_FILES=data.nt -QLEVER_INDEX_CAT_INPUT_FILES=cat data.nt +QLEVER_INDEX_INPUT_FILES=../input/data.nt +QLEVER_INDEX_CAT_INPUT_FILES=cat ../input/data.nt # QLEVER_INDEX_SETTINGS_JSON={ "ascii-prefixes-only": false, "num-triples-per-batch": 100000 } # [server] +QLEVER_SERVER_HOST_NAME=0.0.0.0 QLEVER_SERVER_PORT=7001 QLEVER_SERVER_MEMORY_FOR_QUERIES=8G QLEVER_SERVER_CACHE_MAX_SIZE=4G @@ -32,3 +33,6 @@ FORCE_INDEXING=false STOP_ON_CALL_ENABLED=false START_ADDITIONAL_ARGS= + +UID=501 +GID=20 \ No newline at end of file diff --git a/infra/qlever/scripts/entrypoint.sh b/infra/qlever/scripts/entrypoint.sh index da33689..188de08 100644 --- a/infra/qlever/scripts/entrypoint.sh +++ b/infra/qlever/scripts/entrypoint.sh @@ -12,13 +12,14 @@ FORCE_DOWNLOAD="${FORCE_DOWNLOAD:-false}" # Additional parameters to qlever start (e.g. --kill-existing-with-same-port) START_ADDITIONAL_ARGS="${START_ADDITIONAL_ARGS:-}" +STOP_ON_CALL_ENABLED="${STOP_ON_CALL_ENABLED:-false}" # Display some debug information echo "INFO: Indexing : should index = ${SHOULD_INDEX} ; force indexing = ${FORCE_INDEXING}" echo "INFO: Data download : should download = ${SHOULD_DOWNLOAD} ; force download = ${FORCE_DOWNLOAD}" # Generate Qleverfile (or skip, depending on QLEVER_GENERATE_CONFIG_FILE) - /qlever/scripts/generate-qleverfile.sh +/bin/sh /qlever/scripts/generate-qleverfile.sh # Go to the data directory cd /data