From c607e77fe9ffb1aeda92ca1f39b1a050e934f395 Mon Sep 17 00:00:00 2001 From: Ivan Gabaldon Date: Tue, 20 May 2025 12:04:54 +0200 Subject: [PATCH] [mod] container: replace uWSGI with Granian The configuration in Granian is handled with ENVs, much more convenient and practical for updating. The settings have been tested for over two months in a production instance, being usable on small to somewhat large instances without having to modify anything. It also removes the patch functions and ENVs abstraction from the entrypoint, this makes it possible to run the container with immutable configuration. In some setups, It may be desired to have the volumes/files under a specific uid/gid (other than searxng:searxng), if the entrypoint has root permissions it will chown automatically on every start, which may not be desired. Explicitly setting the new ENV `FORCE_OWNERSHIP=false` will prevent ownership from being modified. No manual migration is necessary **unless** the user has changed the default uWSGI configuration or has a very specific setup. Closes https://github.com/searxng/searxng/issues/4894 Closes https://github.com/searxng/searxng/issues/4818 Closes https://github.com/searxng/searxng/issues/4802 Supersedes https://github.com/searxng/searxng/pull/4596 Related https://github.com/searxng/searxng/discussions/4479 --- container/Dockerfile | 31 ++++++++------ container/base-builder.yml | 2 - container/base.yml | 3 -- container/config/uwsgi.ini | 55 ------------------------ container/entrypoint.sh | 68 +++++++----------------------- container/template/.empty | 0 docs/admin/installation-docker.rst | 5 --- utils/lib_sxng_container.sh | 1 - 8 files changed, 34 insertions(+), 131 deletions(-) delete mode 100644 container/config/uwsgi.ini create mode 100644 container/template/.empty diff --git a/container/Dockerfile b/container/Dockerfile index 880ae26fc..6632c287e 100644 --- a/container/Dockerfile +++ b/container/Dockerfile @@ -5,7 +5,7 @@ COPY ./requirements.txt ./requirements.txt RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \ && . ./venv/bin/activate \ && pip install -r requirements.txt \ - && pip install "uwsgi~=2.0" + && pip install "granian~=2.0" COPY ./searx/ ./searx/ @@ -27,13 +27,9 @@ ARG LABEL_VCS_URL="unspecified" COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/ COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/ -COPY --chown=searxng:searxng ./container/config/ ./.template/ +COPY --chown=searxng:searxng ./container/template/ ./.template/ COPY --chown=searxng:searxng ./container/entrypoint.sh ./entrypoint.sh -ARG TIMESTAMP_UWSGI="0" - -RUN touch -c --date=@$TIMESTAMP_UWSGI ./.template/uwsgi.ini - LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \ org.opencontainers.image.created="$LABEL_DATE" \ org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \ @@ -46,14 +42,23 @@ LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \ org.opencontainers.image.version="$SEARXNG_GIT_VERSION" ENV SEARXNG_VERSION="$SEARXNG_GIT_VERSION" \ - INSTANCE_NAME="SearXNG" \ - AUTOCOMPLETE="" \ - BASE_URL="" \ - BIND_ADDRESS="[::]:8080" \ SEARXNG_SETTINGS_PATH="$CONFIG_PATH/settings.yml" \ - UWSGI_SETTINGS_PATH="$CONFIG_PATH/uwsgi.ini" \ - UWSGI_WORKERS="%k" \ - UWSGI_THREADS="4" + GRANIAN_PROCESS_NAME="searxng" \ + GRANIAN_INTERFACE="wsgi" \ + GRANIAN_HOST="::" \ + GRANIAN_PORT="8080" \ + # https://github.com/emmett-framework/granian/issues/568 + GRANIAN_HTTP1_KEEP_ALIVE="false" \ + GRANIAN_WEBSOCKETS="false" \ + GRANIAN_LOOP="uvloop" \ + GRANIAN_BLOCKING_THREADS="2" \ + GRANIAN_RUNTIME_THREADS="3" \ + GRANIAN_RUNTIME_BLOCKING_THREADS="2" \ + GRANIAN_RESPAWN_INTERVAL="0" \ + GRANIAN_WORKERS_KILL_TIMEOUT="30" \ + GRANIAN_BACKPRESSURE="1024" \ + GRANIAN_STATIC_PATH_MOUNT="/usr/local/searxng/searx/static/" \ + GRANIAN_STATIC_PATH_EXPIRES="3600" VOLUME $CONFIG_PATH VOLUME $DATA_PATH diff --git a/container/base-builder.yml b/container/base-builder.yml index d6566f790..928e09232 100644 --- a/container/base-builder.yml +++ b/container/base-builder.yml @@ -8,8 +8,6 @@ contents: - python3-dev - py3-pip - brotli - # uwsgi - - libffi-dev entrypoint: command: /bin/sh -l diff --git a/container/base.yml b/container/base.yml index e0a3d9d07..0fb742595 100644 --- a/container/base.yml +++ b/container/base.yml @@ -8,9 +8,6 @@ contents: - python3 # healthcheck - wget - # uwsgi - - libxml2 - - mailcap entrypoint: command: /bin/sh -l diff --git a/container/config/uwsgi.ini b/container/config/uwsgi.ini deleted file mode 100644 index 3bfd49e72..000000000 --- a/container/config/uwsgi.ini +++ /dev/null @@ -1,55 +0,0 @@ -[uwsgi] -# Listening address -# default value: [::]:8080 (see Dockerfile) -http-socket = $(BIND_ADDRESS) - -# Who will run the code -uid = searxng -gid = searxng - -# Number of workers (usually CPU count) -# default value: %k (= number of CPU core, see Dockerfile) -workers = $(UWSGI_WORKERS) - -# Number of threads per worker -# default value: 4 (see Dockerfile) -threads = $(UWSGI_THREADS) - -# The right granted on the created socket -chmod-socket = 666 - -# Plugin to use and interpreter config -single-interpreter = true -master = true -lazy-apps = true -enable-threads = true - -# Module to import -module = searx.webapp - -# Virtualenv and python path -pythonpath = /usr/local/searxng/ -chdir = /usr/local/searxng/searx/ - -# automatically set processes name to something meaningful -auto-procname = true - -# Disable request logging for privacy -disable-logging = true -log-5xx = true - -# Set the max size of a request (request-body excluded) -buffer-size = 8192 - -# No keep alive -# See https://github.com/searx/searx-docker/issues/24 -add-header = Connection: close - -# Follow SIGTERM convention -# See https://github.com/searxng/searxng/issues/3427 -die-on-term - -# uwsgi serves the static files -static-map = /static=/usr/local/searxng/searx/static -static-gzip-all = True -offload-threads = %k diff --git a/container/entrypoint.sh b/container/entrypoint.sh index 8fbdb6947..d9b6b91de 100755 --- a/container/entrypoint.sh +++ b/container/entrypoint.sh @@ -2,6 +2,7 @@ # shellcheck shell=dash set -u +# Check if it's a valid file check_file() { local target="$1" @@ -16,6 +17,7 @@ EOF fi } +# Check if it's a valid directory check_directory() { local target="$1" @@ -47,66 +49,30 @@ EOF ;; esac - if [ "$(stat -c %U:%G "$target")" != "searxng:searxng" ]; then - if [ "$(id -u)" -eq 0 ]; then + target_ownership=$(stat -c %U:%G "$target") + + if [ "$target_ownership" != "searxng:searxng" ]; then + if [ "${FORCE_OWNERSHIP:-true}" = true ] && [ "$(id -u)" -eq 0 ]; then chown -R searxng:searxng "$target" else cat <`_: $ docker run --rm \ -d -p ${PORT}:8080 \ -v "${PWD}/searxng:/etc/searxng" \ - -e "BASE_URL=http://localhost:$PORT/" \ - -e "INSTANCE_NAME=my-instance" \ searxng/searxng 2f998.... # container's ID -The environment variables UWSGI_WORKERS and UWSGI_THREADS overwrite the default -number of UWSGI processes and UWSGI threads specified in `/etc/searxng/uwsgi.ini`. - Open your WEB browser and visit the URL: .. code:: sh diff --git a/utils/lib_sxng_container.sh b/utils/lib_sxng_container.sh index b1e80717b..9abed5afb 100644 --- a/utils/lib_sxng_container.sh +++ b/utils/lib_sxng_container.sh @@ -122,7 +122,6 @@ container.build() { # shellcheck disable=SC2086 "$container_engine" $params_build \ --build-arg="TIMESTAMP_SETTINGS=$(git log -1 --format="%cd" --date=unix -- ./searx/settings.yml)" \ - --build-arg="TIMESTAMP_UWSGI=$(git log -1 --format="%cd" --date=unix -- ./container/config/uwsgi.ini)" \ --build-arg="GIT_URL=$GIT_URL" \ --build-arg="SEARXNG_GIT_VERSION=$VERSION_STRING" \ --build-arg="LABEL_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \