Browse Source

Rework Dockerfile (#4699)

This is one of various PR to refactor the entire SearXNG Docker workflow.

Switches to Python glibc based images, all dependencies are installed via pip and not from system repositories, and several minor changes.

This PR will increase the image size from 194.9 MB to 345.47 MB (amd64), this is due to ARMv7 images (needs dependencies for wheels compilation and runtime (?)) and uWSGI webserver. Later PR will reduce the final image size.
Ivan Gabaldon 2 days ago
parent
commit
2e74d86321
3 changed files with 94 additions and 95 deletions
  1. 91 79
      Dockerfile
  2. 3 11
      dockerfiles/docker-entrypoint.sh
  3. 0 5
      dockerfiles/uwsgi.ini

+ 91 - 79
Dockerfile

@@ -1,92 +1,104 @@
-FROM alpine:3.20
-ENTRYPOINT ["/sbin/tini","--","/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
-EXPOSE 8080
-VOLUME /etc/searxng
+FROM --platform=$TARGETPLATFORM docker.io/library/python:3.13-slim AS builder
 
-ARG SEARXNG_GID=977
-ARG SEARXNG_UID=977
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    build-essential \
+    brotli \
+    # lxml
+    libxml2-dev \
+    libxslt1-dev \
+    zlib1g-dev \
+    # uwsgi
+    libpcre3-dev \
+ && rm -rf /var/lib/apt/lists/*
 
-RUN addgroup -g ${SEARXNG_GID} searxng && \
-    adduser -u ${SEARXNG_UID} -D -h /usr/local/searxng -s /bin/sh -G searxng searxng
+WORKDIR /usr/local/searxng/
 
-ENV INSTANCE_NAME=searxng \
-    AUTOCOMPLETE= \
-    BASE_URL= \
-    BIND_ADDRESS=[::]:8080 \
-    MORTY_KEY= \
-    MORTY_URL= \
-    SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml \
-    UWSGI_SETTINGS_PATH=/etc/searxng/uwsgi.ini \
-    UWSGI_WORKERS=%k \
-    UWSGI_THREADS=4
+COPY ./requirements.txt ./requirements.txt
 
-WORKDIR /usr/local/searxng
+RUN --mount=type=cache,id=pip,target=$HOME/.cache/pip python -m venv ./venv \
+ && . ./venv/bin/activate \
+ && pip install -r requirements.txt \
+ && pip install "uwsgi~=2.0"
 
-COPY requirements.txt ./requirements.txt
+COPY ./searx/ ./searx/
 
-RUN apk add --no-cache -t build-dependencies \
-    build-base \
-    py3-setuptools \
-    python3-dev \
-    libffi-dev \
-    libxslt-dev \
-    libxml2-dev \
-    openssl-dev \
-    tar \
-    git \
- && apk add --no-cache \
-    ca-certificates \
-    python3 \
-    py3-pip \
+ARG TIMESTAMP_SETTINGS=0
+ARG TIMESTAMP_UWSGI=0
+
+RUN python -m compileall -q searx \
+ && touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
+ && touch -c --date=@$TIMESTAMP_UWSGI ./dockerfiles/uwsgi.ini \
+ && find /usr/local/searxng/searx/static \
+    \( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
+    -type f -exec gzip -9 -k {} + -exec brotli --best {} +
+
+ARG SEARXNG_UID=977
+ARG SEARXNG_GID=977
+
+RUN grep -m1 root /etc/group > /tmp/.searxng.group \
+ && grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
+ && echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
+ && echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
+
+FROM --platform=$TARGETPLATFORM docker.io/library/python:3.13-slim
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    # uwsgi
+    libpcre3 \
     libxml2 \
-    libxslt \
-    openssl \
-    tini \
-    uwsgi \
-    uwsgi-python3 \
-    brotli \
- && pip3 install --break-system-packages --no-cache -r requirements.txt \
- && apk del build-dependencies \
- && rm -rf /root/.cache
+    mailcap \
+ && rm -rf /var/lib/apt/lists/*
 
-COPY --chown=searxng:searxng dockerfiles ./dockerfiles
-COPY --chown=searxng:searxng searx ./searx
+COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
+COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
 
-ARG TIMESTAMP_SETTINGS=0
-ARG TIMESTAMP_UWSGI=0
-ARG VERSION_GITCOMMIT=unknown
+ARG LABEL_DATE="0001-01-01T00:00:00Z"
+ARG GIT_URL="unspecified"
+ARG SEARXNG_GIT_VERSION="unspecified"
+ARG LABEL_VCS_REF="unspecified"
+ARG LABEL_VCS_URL="unspecified"
 
-RUN su searxng -c "/usr/bin/python3 -m compileall -q searx" \
- && touch -c --date=@${TIMESTAMP_SETTINGS} searx/settings.yml \
- && touch -c --date=@${TIMESTAMP_UWSGI} dockerfiles/uwsgi.ini \
- && find /usr/local/searxng/searx/static -a \( -name '*.html' -o -name '*.css' -o -name '*.js' \
-    -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-    -type f -exec gzip -9 -k {} \+ -exec brotli --best {} \+
+WORKDIR /usr/local/searxng/
 
-HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
+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 ./dockerfiles/ ./dockerfiles/
 
-# Keep these arguments at the end to prevent redundant layer rebuilds
-ARG LABEL_DATE=
-ARG GIT_URL=unknown
-ARG SEARXNG_GIT_VERSION=unknown
-ARG SEARXNG_DOCKER_TAG=unknown
-ARG LABEL_VCS_REF=
-ARG LABEL_VCS_URL=
-LABEL maintainer="searxng <${GIT_URL}>" \
-      description="A privacy-respecting, hackable metasearch engine." \
-      version="${SEARXNG_GIT_VERSION}" \
-      org.label-schema.schema-version="1.0" \
-      org.label-schema.name="searxng" \
-      org.label-schema.version="${SEARXNG_GIT_VERSION}" \
-      org.label-schema.url="${LABEL_VCS_URL}" \
-      org.label-schema.vcs-ref=${LABEL_VCS_REF} \
-      org.label-schema.vcs-url=${LABEL_VCS_URL} \
-      org.label-schema.build-date="${LABEL_DATE}" \
-      org.label-schema.usage="https://github.com/searxng/searxng-docker" \
+LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
+      org.opencontainers.image.created=$LABEL_DATE \
+      org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
+      org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
+      org.opencontainers.image.licenses="AGPL-3.0-or-later" \
+      org.opencontainers.image.revision=$LABEL_VCS_REF \
+      org.opencontainers.image.source=$LABEL_VCS_URL \
       org.opencontainers.image.title="searxng" \
-      org.opencontainers.image.version="${SEARXNG_DOCKER_TAG}" \
-      org.opencontainers.image.url="${LABEL_VCS_URL}" \
-      org.opencontainers.image.revision=${LABEL_VCS_REF} \
-      org.opencontainers.image.source=${LABEL_VCS_URL} \
-      org.opencontainers.image.created="${LABEL_DATE}" \
-      org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker"
+      org.opencontainers.image.url=$LABEL_VCS_URL \
+      org.opencontainers.image.version=$SEARXNG_GIT_VERSION
+
+ENV CONFIG_PATH=/etc/searxng \
+    DATA_PATH=/var/cache/searxng
+
+ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
+    INSTANCE_NAME=searxng \
+    AUTOCOMPLETE="" \
+    BASE_URL="" \
+    BIND_ADDRESS=[::]:8080 \
+    MORTY_KEY="" \
+    MORTY_URL="" \
+    SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
+    UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
+    UWSGI_WORKERS=%k \
+    UWSGI_THREADS=4
+
+VOLUME $CONFIG_PATH
+VOLUME $DATA_PATH
+
+EXPOSE 8080
+
+USER searxng:searxng
+
+HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
+
+ENTRYPOINT ["/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]

+ 3 - 11
dockerfiles/docker-entrypoint.sh

@@ -43,15 +43,7 @@ do
     esac
 done
 
-get_searxng_version(){
-    su searxng -c \
-       'python3 -c "import six; import searx.version; six.print_(searx.version.VERSION_STRING)"' \
-       2>/dev/null
-}
-
-SEARXNG_VERSION="$(get_searxng_version)"
-export SEARXNG_VERSION
-echo "SearXNG version ${SEARXNG_VERSION}"
+echo "SearXNG version $SEARXNG_VERSION"
 
 # helpers to update the configuration files
 patch_uwsgi_settings() {
@@ -76,7 +68,7 @@ patch_searxng_settings() {
         -e "s|base_url: false|base_url: ${BASE_URL}|g" \
         -e "s/instance_name: \"SearXNG\"/instance_name: \"${INSTANCE_NAME}\"/g" \
         -e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
-        -e "s/ultrasecretkey/$(openssl rand -hex 32)/g" \
+        -e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
         "${CONF}"
 
     # Morty configuration
@@ -172,4 +164,4 @@ printf 'Listen on %s\n' "${BIND_ADDRESS}"
 
 # Start uwsgi
 # TODO: "--http-socket" will be removed in the future (see uwsgi.ini.new config file): https://github.com/searxng/searxng/pull/4578
-exec uwsgi --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"
+exec /usr/local/searxng/venv/bin/uwsgi --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"

+ 0 - 5
dockerfiles/uwsgi.ini

@@ -3,10 +3,6 @@
 # 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)
@@ -21,7 +17,6 @@ chmod-socket = 666
 # Plugin to use and interpreter config
 single-interpreter = true
 master = true
-plugin = python3
 lazy-apps = true
 enable-threads = true