mirror of
https://github.com/searxng/searxng.git
synced 2025-08-12 06:46:47 +02:00
[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
This commit is contained in:
parent
df76647c52
commit
c607e77fe9
8 changed files with 34 additions and 131 deletions
|
@ -5,7 +5,7 @@ COPY ./requirements.txt ./requirements.txt
|
||||||
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
|
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
|
||||||
&& . ./venv/bin/activate \
|
&& . ./venv/bin/activate \
|
||||||
&& pip install -r requirements.txt \
|
&& pip install -r requirements.txt \
|
||||||
&& pip install "uwsgi~=2.0"
|
&& pip install "granian~=2.0"
|
||||||
|
|
||||||
COPY ./searx/ ./searx/
|
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/venv/ ./venv/
|
||||||
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
|
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
|
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>" \
|
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
|
||||||
org.opencontainers.image.created="$LABEL_DATE" \
|
org.opencontainers.image.created="$LABEL_DATE" \
|
||||||
org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
|
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"
|
org.opencontainers.image.version="$SEARXNG_GIT_VERSION"
|
||||||
|
|
||||||
ENV SEARXNG_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" \
|
SEARXNG_SETTINGS_PATH="$CONFIG_PATH/settings.yml" \
|
||||||
UWSGI_SETTINGS_PATH="$CONFIG_PATH/uwsgi.ini" \
|
GRANIAN_PROCESS_NAME="searxng" \
|
||||||
UWSGI_WORKERS="%k" \
|
GRANIAN_INTERFACE="wsgi" \
|
||||||
UWSGI_THREADS="4"
|
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 $CONFIG_PATH
|
||||||
VOLUME $DATA_PATH
|
VOLUME $DATA_PATH
|
||||||
|
|
|
@ -8,8 +8,6 @@ contents:
|
||||||
- python3-dev
|
- python3-dev
|
||||||
- py3-pip
|
- py3-pip
|
||||||
- brotli
|
- brotli
|
||||||
# uwsgi
|
|
||||||
- libffi-dev
|
|
||||||
|
|
||||||
entrypoint:
|
entrypoint:
|
||||||
command: /bin/sh -l
|
command: /bin/sh -l
|
||||||
|
|
|
@ -8,9 +8,6 @@ contents:
|
||||||
- python3
|
- python3
|
||||||
# healthcheck
|
# healthcheck
|
||||||
- wget
|
- wget
|
||||||
# uwsgi
|
|
||||||
- libxml2
|
|
||||||
- mailcap
|
|
||||||
|
|
||||||
entrypoint:
|
entrypoint:
|
||||||
command: /bin/sh -l
|
command: /bin/sh -l
|
||||||
|
|
|
@ -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
|
|
|
@ -2,6 +2,7 @@
|
||||||
# shellcheck shell=dash
|
# shellcheck shell=dash
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
|
# Check if it's a valid file
|
||||||
check_file() {
|
check_file() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ EOF
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if it's a valid directory
|
||||||
check_directory() {
|
check_directory() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
|
|
||||||
|
@ -47,66 +49,30 @@ EOF
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$(stat -c %U:%G "$target")" != "searxng:searxng" ]; then
|
target_ownership=$(stat -c %U:%G "$target")
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
|
||||||
|
if [ "$target_ownership" != "searxng:searxng" ]; then
|
||||||
|
if [ "${FORCE_OWNERSHIP:-true}" = true ] && [ "$(id -u)" -eq 0 ]; then
|
||||||
chown -R searxng:searxng "$target"
|
chown -R searxng:searxng "$target"
|
||||||
else
|
else
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
!!!
|
!!!
|
||||||
!!! WARNING
|
!!! WARNING
|
||||||
!!! "$target" $type is not owned by "searxng"
|
!!! "$target" $type is not owned by "searxng:searxng"
|
||||||
!!! This may cause issues when running SearXNG
|
!!! This may cause issues when running SearXNG
|
||||||
!!!
|
!!!
|
||||||
!!! Run the container as root to fix this issue automatically
|
!!! Expected "searxng:searxng"
|
||||||
!!! Alternatively, you can chown the $type manually:
|
!!! Got "$target_ownership"
|
||||||
!!! $ chown -R searxng:searxng "$target"
|
|
||||||
!!!
|
!!!
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Apply envs to uwsgi.ini
|
|
||||||
setup_uwsgi() {
|
|
||||||
local timestamp
|
|
||||||
|
|
||||||
timestamp=$(stat -c %Y "$UWSGI_SETTINGS_PATH")
|
|
||||||
|
|
||||||
sed -i \
|
|
||||||
-e "s|workers = .*|workers = ${UWSGI_WORKERS:-%k}|g" \
|
|
||||||
-e "s|threads = .*|threads = ${UWSGI_THREADS:-4}|g" \
|
|
||||||
"$UWSGI_SETTINGS_PATH"
|
|
||||||
|
|
||||||
# Restore timestamp
|
|
||||||
touch -c -d "@$timestamp" "$UWSGI_SETTINGS_PATH"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Apply envs to settings.yml
|
|
||||||
setup_searxng() {
|
|
||||||
local timestamp
|
|
||||||
|
|
||||||
timestamp=$(stat -c %Y "$SEARXNG_SETTINGS_PATH")
|
|
||||||
|
|
||||||
# Ensure trailing slash in BASE_URL
|
|
||||||
# https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
|
|
||||||
export BASE_URL="${BASE_URL%/}/"
|
|
||||||
|
|
||||||
sed -i \
|
|
||||||
-e "s|base_url: false|base_url: ${BASE_URL:-false}|g" \
|
|
||||||
-e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME:-SearXNG}\"/g" \
|
|
||||||
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE:-}\"/g" \
|
|
||||||
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
|
|
||||||
"$SEARXNG_SETTINGS_PATH"
|
|
||||||
|
|
||||||
# Restore timestamp
|
|
||||||
touch -c -d "@$timestamp" "$SEARXNG_SETTINGS_PATH"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Handle volume mounts
|
# Handle volume mounts
|
||||||
volume_handler() {
|
volume_handler() {
|
||||||
local target="$1"
|
local target="$1"
|
||||||
|
|
||||||
# Check if it's a valid directory
|
|
||||||
check_directory "$target"
|
check_directory "$target"
|
||||||
setup_ownership "$target" "directory"
|
setup_ownership "$target" "directory"
|
||||||
}
|
}
|
||||||
|
@ -143,24 +109,22 @@ EOF
|
||||||
...
|
...
|
||||||
EOF
|
EOF
|
||||||
cp -pfT "$template" "$target"
|
cp -pfT "$template" "$target"
|
||||||
|
|
||||||
|
sed -i "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" "$target"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if it's a valid file
|
|
||||||
check_file "$target"
|
check_file "$target"
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "SearXNG $SEARXNG_VERSION"
|
cat <<EOF
|
||||||
|
SearXNG $SEARXNG_VERSION
|
||||||
|
EOF
|
||||||
|
|
||||||
# Check for volume mounts
|
# Check for volume mounts
|
||||||
volume_handler "$CONFIG_PATH"
|
volume_handler "$CONFIG_PATH"
|
||||||
volume_handler "$DATA_PATH"
|
volume_handler "$DATA_PATH"
|
||||||
|
|
||||||
# Check for updates in files
|
# Check for files
|
||||||
config_handler "$UWSGI_SETTINGS_PATH" "/usr/local/searxng/.template/uwsgi.ini"
|
|
||||||
config_handler "$SEARXNG_SETTINGS_PATH" "/usr/local/searxng/searx/settings.yml"
|
config_handler "$SEARXNG_SETTINGS_PATH" "/usr/local/searxng/searx/settings.yml"
|
||||||
|
|
||||||
# Update files
|
exec /usr/local/searxng/venv/bin/granian searx.webapp:app
|
||||||
setup_uwsgi
|
|
||||||
setup_searxng
|
|
||||||
|
|
||||||
exec /usr/local/searxng/venv/bin/uwsgi --http-socket "$BIND_ADDRESS" "$UWSGI_SETTINGS_PATH"
|
|
||||||
|
|
0
container/template/.empty
Normal file
0
container/template/.empty
Normal file
|
@ -87,14 +87,9 @@ instance using `docker run <https://docs.docker.com/engine/reference/run/>`_:
|
||||||
$ docker run --rm \
|
$ docker run --rm \
|
||||||
-d -p ${PORT}:8080 \
|
-d -p ${PORT}:8080 \
|
||||||
-v "${PWD}/searxng:/etc/searxng" \
|
-v "${PWD}/searxng:/etc/searxng" \
|
||||||
-e "BASE_URL=http://localhost:$PORT/" \
|
|
||||||
-e "INSTANCE_NAME=my-instance" \
|
|
||||||
searxng/searxng
|
searxng/searxng
|
||||||
2f998.... # container's ID
|
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:
|
Open your WEB browser and visit the URL:
|
||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
|
@ -122,7 +122,6 @@ container.build() {
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
"$container_engine" $params_build \
|
"$container_engine" $params_build \
|
||||||
--build-arg="TIMESTAMP_SETTINGS=$(git log -1 --format="%cd" --date=unix -- ./searx/settings.yml)" \
|
--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="GIT_URL=$GIT_URL" \
|
||||||
--build-arg="SEARXNG_GIT_VERSION=$VERSION_STRING" \
|
--build-arg="SEARXNG_GIT_VERSION=$VERSION_STRING" \
|
||||||
--build-arg="LABEL_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
--build-arg="LABEL_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue