[mod] rework container deployment
container.yml will run after integration.yml COMPLETES successfully and in master branch. Style changes, cleanup and improved integration with CI by leveraging the use of shared cache between all workflows. * Podman is now supported to build the container images (Docker also received a refactor, merging both build and buildx) * Container images are being built by Buildah instead of Docker BuildKit. * Container images are tested before release. * Splitting "modern" (amd64 & arm64) and "legacy" (armv7) arches on different Dockerfiles allowing future optimizations.
This commit is contained in:
parent
1b787ed35e
commit
2bc305782c
182
.github/workflows/container.yml
vendored
Normal file
182
.github/workflows/container.yml
vendored
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
---
|
||||||
|
name: Container
|
||||||
|
|
||||||
|
# yamllint disable-line rule:truthy
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- Integration
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
# Organization GHCR
|
||||||
|
packages: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: "3.13"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
|
||||||
|
name: Build (${{ matrix.arch }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: amd64
|
||||||
|
os: ubuntu-24.04
|
||||||
|
emulation: false
|
||||||
|
- arch: arm64
|
||||||
|
os: ubuntu-24.04-arm
|
||||||
|
emulation: false
|
||||||
|
- arch: armv7
|
||||||
|
os: ubuntu-24.04-arm
|
||||||
|
emulation: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
# Organization GHCR
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
version_string: ${{ steps.build.outputs.version_string }}
|
||||||
|
version_tag: ${{ steps.build.outputs.version_tag }}
|
||||||
|
docker_tag: ${{ steps.build.outputs.docker_tag }}
|
||||||
|
git_url: ${{ steps.build.outputs.git_url }}
|
||||||
|
git_branch: ${{ steps.build.outputs.git_branch }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "${{ env.PYTHON_VERSION }}"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: "false"
|
||||||
|
|
||||||
|
- name: Setup cache Python
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
|
||||||
|
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
|
||||||
|
path: "./local/"
|
||||||
|
|
||||||
|
- name: Setup cache container mounts
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./Dockerfile*') }}"
|
||||||
|
restore-keys: "container-mounts-${{ matrix.arch }}-"
|
||||||
|
path: |
|
||||||
|
/var/tmp/buildah-cache/
|
||||||
|
/var/tmp/buildah-cache-*/
|
||||||
|
|
||||||
|
- if: ${{ matrix.emulation }}
|
||||||
|
name: Setup QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: "ghcr.io"
|
||||||
|
username: "${{ github.repository_owner }}"
|
||||||
|
password: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
id: build
|
||||||
|
env:
|
||||||
|
OVERRIDE_ARCH: "${{ matrix.arch }}"
|
||||||
|
run: make podman.build
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test (${{ matrix.arch }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: amd64
|
||||||
|
os: ubuntu-24.04
|
||||||
|
emulation: false
|
||||||
|
- arch: arm64
|
||||||
|
os: ubuntu-24.04-arm
|
||||||
|
emulation: false
|
||||||
|
- arch: armv7
|
||||||
|
os: ubuntu-24.04-arm
|
||||||
|
emulation: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
# Organization GHCR
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: "false"
|
||||||
|
|
||||||
|
- if: ${{ matrix.emulation }}
|
||||||
|
name: Setup QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: "ghcr.io"
|
||||||
|
username: "${{ github.repository_owner }}"
|
||||||
|
password: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
env:
|
||||||
|
OVERRIDE_ARCH: "${{ matrix.arch }}"
|
||||||
|
GIT_URL: "${{ needs.build.outputs.git_url }}"
|
||||||
|
run: make container.test
|
||||||
|
|
||||||
|
release:
|
||||||
|
if: github.repository_owner == 'searxng' && github.ref_name == 'master'
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- if: env.DOCKERHUB_USERNAME != ''
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: "false"
|
||||||
|
|
||||||
|
- if: env.DOCKERHUB_USERNAME != ''
|
||||||
|
name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: "ghcr.io"
|
||||||
|
username: "${{ github.repository_owner }}"
|
||||||
|
password: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- if: env.DOCKERHUB_USERNAME != ''
|
||||||
|
name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: "docker.io"
|
||||||
|
username: "${{ env.DOCKERHUB_USERNAME }}"
|
||||||
|
password: "${{ secrets.DOCKERHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- if: env.DOCKERHUB_USERNAME != ''
|
||||||
|
name: Release
|
||||||
|
env:
|
||||||
|
GIT_URL: "${{ needs.build.outputs.git_url }}"
|
||||||
|
DOCKER_TAG: "${{ needs.build.outputs.docker_tag }}"
|
||||||
|
run: make container.push
|
46
.github/workflows/integration.yml
vendored
46
.github/workflows/integration.yml
vendored
@ -94,49 +94,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: make themes.all
|
run: make themes.all
|
||||||
|
|
||||||
dockers:
|
|
||||||
name: Docker
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
needs:
|
|
||||||
- test
|
|
||||||
- theme
|
|
||||||
env:
|
|
||||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# make sure "make docker.push" can get the git history
|
|
||||||
fetch-depth: '0'
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.12'
|
|
||||||
architecture: 'x64'
|
|
||||||
- name: Cache Python dependencies
|
|
||||||
id: cache-python
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
./local
|
|
||||||
./.nvm
|
|
||||||
./node_modules
|
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
|
||||||
- name: Set up QEMU
|
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
- name: Login to DockerHub
|
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Build and push
|
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
|
||||||
run: make -e GIT_URL=$(git remote get-url origin) docker.buildx
|
|
||||||
|
@ -4,10 +4,6 @@ RUN apt-get update \
|
|||||||
&& apt-get install -y --no-install-recommends \
|
&& apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
brotli \
|
brotli \
|
||||||
# lxml
|
|
||||||
libxml2-dev \
|
|
||||||
libxslt1-dev \
|
|
||||||
zlib1g-dev \
|
|
||||||
# uwsgi
|
# uwsgi
|
||||||
libpcre3-dev \
|
libpcre3-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
@ -16,8 +12,7 @@ WORKDIR /usr/local/searxng/
|
|||||||
|
|
||||||
COPY ./requirements.txt ./requirements.txt
|
COPY ./requirements.txt ./requirements.txt
|
||||||
|
|
||||||
# Readd on #4707 "--mount=type=cache,id=pip,target=/root/.cache/pip"
|
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
|
||||||
RUN 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 "uwsgi~=2.0"
|
||||||
@ -48,8 +43,6 @@ RUN apt-get update \
|
|||||||
&& apt-get install -y --no-install-recommends \
|
&& apt-get install -y --no-install-recommends \
|
||||||
# healthcheck
|
# healthcheck
|
||||||
wget \
|
wget \
|
||||||
# lxml (ARMv7)
|
|
||||||
libxslt1.1 \
|
|
||||||
# uwsgi
|
# uwsgi
|
||||||
libpcre3 \
|
libpcre3 \
|
||||||
libxml2 \
|
libxml2 \
|
||||||
|
8
Makefile
8
Makefile
@ -77,7 +77,9 @@ test.shell:
|
|||||||
MANAGE += weblate.translations.commit weblate.push.translations
|
MANAGE += weblate.translations.commit weblate.push.translations
|
||||||
MANAGE += data.all data.traits data.useragents data.locales data.currencies
|
MANAGE += data.all data.traits data.useragents data.locales data.currencies
|
||||||
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
|
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
|
||||||
MANAGE += docker.build docker.push docker.buildx
|
MANAGE += podman.build
|
||||||
|
MANAGE += docker.build docker.buildx
|
||||||
|
MANAGE += container.build container.test container.push
|
||||||
MANAGE += gecko.driver
|
MANAGE += gecko.driver
|
||||||
MANAGE += node.env node.env.dev node.clean
|
MANAGE += node.env node.env.dev node.clean
|
||||||
MANAGE += py.build py.clean
|
MANAGE += py.build py.clean
|
||||||
@ -95,8 +97,8 @@ $(MANAGE):
|
|||||||
|
|
||||||
# short hands of selected targets
|
# short hands of selected targets
|
||||||
|
|
||||||
PHONY += docs docker themes
|
PHONY += docs container themes
|
||||||
|
|
||||||
docs: docs.html
|
docs: docs.html
|
||||||
docker: docker.build
|
container: container.build
|
||||||
themes: themes.all
|
themes: themes.all
|
||||||
|
104
armv7.dockerfile
Normal file
104
armv7.dockerfile
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
FROM docker.io/library/python:3.13-slim AS builder
|
||||||
|
|
||||||
|
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/*
|
||||||
|
|
||||||
|
WORKDIR /usr/local/searxng/
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
COPY ./searx/ ./searx/
|
||||||
|
|
||||||
|
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 docker.io/library/python:3.13-slim
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
# healthcheck
|
||||||
|
wget \
|
||||||
|
# lxml (ARMv7)
|
||||||
|
libxslt1.1 \
|
||||||
|
# uwsgi
|
||||||
|
libpcre3 \
|
||||||
|
libxml2 \
|
||||||
|
mailcap \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
|
||||||
|
COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
WORKDIR /usr/local/searxng/
|
||||||
|
|
||||||
|
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/
|
||||||
|
|
||||||
|
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.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 \
|
||||||
|
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
|
||||||
|
|
||||||
|
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
|
91
manage
91
manage
@ -11,6 +11,9 @@ source "$(dirname "${BASH_SOURCE[0]}")/utils/lib.sh"
|
|||||||
# shellcheck source=utils/lib.sh
|
# shellcheck source=utils/lib.sh
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_nvm.sh"
|
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_nvm.sh"
|
||||||
|
|
||||||
|
# shellcheck source=utils/lib_sxng_container.sh
|
||||||
|
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_container.sh"
|
||||||
|
|
||||||
# shellcheck source=utils/lib_sxng_data.sh
|
# shellcheck source=utils/lib_sxng_data.sh
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_data.sh"
|
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_data.sh"
|
||||||
|
|
||||||
@ -77,9 +80,6 @@ docs.:
|
|||||||
gh-pages : deploy on gh-pages branch
|
gh-pages : deploy on gh-pages branch
|
||||||
prebuild : build reST include files (./${DOCS_BUILD}/includes)
|
prebuild : build reST include files (./${DOCS_BUILD}/includes)
|
||||||
clean : clean documentation build
|
clean : clean documentation build
|
||||||
docker.:
|
|
||||||
build : build docker image
|
|
||||||
push : build and push docker image
|
|
||||||
gecko.driver:
|
gecko.driver:
|
||||||
download & install geckodriver if not already installed (required for
|
download & install geckodriver if not already installed (required for
|
||||||
robot_tests)
|
robot_tests)
|
||||||
@ -101,6 +101,7 @@ EOF
|
|||||||
go.help
|
go.help
|
||||||
node.help
|
node.help
|
||||||
weblate.help
|
weblate.help
|
||||||
|
container.help
|
||||||
data.help
|
data.help
|
||||||
test.help
|
test.help
|
||||||
themes.help
|
themes.help
|
||||||
@ -136,90 +137,6 @@ webapp.run() {
|
|||||||
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
|
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
|
||||||
}
|
}
|
||||||
|
|
||||||
docker.push() {
|
|
||||||
docker.build push
|
|
||||||
}
|
|
||||||
|
|
||||||
docker.buildx() {
|
|
||||||
docker.build buildx
|
|
||||||
}
|
|
||||||
|
|
||||||
# shellcheck disable=SC2119
|
|
||||||
docker.build() {
|
|
||||||
pyenv.install
|
|
||||||
|
|
||||||
local SEARXNG_GIT_VERSION
|
|
||||||
local VERSION_GITCOMMIT
|
|
||||||
local GITHUB_USER
|
|
||||||
local SEARXNG_IMAGE_NAME
|
|
||||||
local BUILD
|
|
||||||
|
|
||||||
build_msg DOCKER build
|
|
||||||
# run installation in a subprocess and activate pyenv
|
|
||||||
|
|
||||||
# See https://www.shellcheck.net/wiki/SC1001 and others ..
|
|
||||||
# shellcheck disable=SC2031,SC2230,SC2002,SC2236,SC2143,SC1001
|
|
||||||
( set -e
|
|
||||||
pyenv.activate
|
|
||||||
|
|
||||||
# Check if it is a git repository
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
die 1 "This is not Git repository"
|
|
||||||
fi
|
|
||||||
if [ ! -x "$(which git)" ]; then
|
|
||||||
die 1 "git is not installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! git remote get-url origin 2> /dev/null; then
|
|
||||||
die 1 "there is no remote origin"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This is a git repository
|
|
||||||
git update-index -q --refresh
|
|
||||||
python -m searx.version freeze
|
|
||||||
eval "$(python -m searx.version)"
|
|
||||||
|
|
||||||
# Get the last git commit id
|
|
||||||
VERSION_GITCOMMIT=$(echo "$VERSION_TAG" | cut -d+ -f2)
|
|
||||||
build_msg DOCKER "Last commit : $VERSION_GITCOMMIT"
|
|
||||||
|
|
||||||
# define the docker image name
|
|
||||||
GITHUB_USER=$(echo "${GIT_URL}" | sed 's/.*github\.com\/\([^\/]*\).*/\1/')
|
|
||||||
SEARXNG_IMAGE_NAME="${SEARXNG_IMAGE_NAME:-${GITHUB_USER:-searxng}/searxng}"
|
|
||||||
|
|
||||||
BUILD="build"
|
|
||||||
if [ "$1" = "buildx" ]; then
|
|
||||||
# buildx includes the push option
|
|
||||||
CACHE_TAG="${SEARXNG_IMAGE_NAME}:latest-build-cache"
|
|
||||||
BUILD="buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push --cache-from=type=registry,ref=$CACHE_TAG --cache-to=type=registry,ref=$CACHE_TAG,mode=max"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
build_msg DOCKER "Build command: ${BUILD}"
|
|
||||||
|
|
||||||
# build Docker image
|
|
||||||
build_msg DOCKER "Building image ${SEARXNG_IMAGE_NAME}:${SEARXNG_GIT_VERSION}"
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
docker $BUILD \
|
|
||||||
--build-arg BASE_IMAGE="${DEPENDENCIES_IMAGE_NAME}" \
|
|
||||||
--build-arg GIT_URL="${GIT_URL}" \
|
|
||||||
--build-arg SEARXNG_DOCKER_TAG="${DOCKER_TAG}" \
|
|
||||||
--build-arg SEARXNG_GIT_VERSION="${VERSION_STRING}" \
|
|
||||||
--build-arg VERSION_GITCOMMIT="${VERSION_GITCOMMIT}" \
|
|
||||||
--build-arg LABEL_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
|
|
||||||
--build-arg LABEL_VCS_REF="$(git rev-parse HEAD)" \
|
|
||||||
--build-arg LABEL_VCS_URL="${GIT_URL}" \
|
|
||||||
--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 -- dockerfiles/uwsgi.ini)" \
|
|
||||||
-t "${SEARXNG_IMAGE_NAME}:latest" -t "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}" .
|
|
||||||
|
|
||||||
if [ "$1" = "push" ]; then
|
|
||||||
docker push "${SEARXNG_IMAGE_NAME}:latest"
|
|
||||||
docker push "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}"
|
|
||||||
fi
|
|
||||||
)
|
|
||||||
dump_return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
# shellcheck disable=SC2119
|
# shellcheck disable=SC2119
|
||||||
gecko.driver() {
|
gecko.driver() {
|
||||||
pyenv.install
|
pyenv.install
|
||||||
|
@ -41,6 +41,12 @@ def subprocess_run(args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def get_git_url_and_branch():
|
def get_git_url_and_branch():
|
||||||
|
# handle GHA directly
|
||||||
|
if "GITHUB_REPOSITORY" in os.environ and "GITHUB_REF_NAME" in os.environ:
|
||||||
|
git_url = f"https://github.com/{os.environ['GITHUB_REPOSITORY']}"
|
||||||
|
git_branch = os.environ["GITHUB_REF_NAME"]
|
||||||
|
return git_url, git_branch
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ref = subprocess_run("git rev-parse --abbrev-ref @{upstream}")
|
ref = subprocess_run("git rev-parse --abbrev-ref @{upstream}")
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
|
319
utils/lib_sxng_container.sh
Normal file
319
utils/lib_sxng_container.sh
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
container.help() {
|
||||||
|
cat <<EOF
|
||||||
|
container.:
|
||||||
|
build : build container image
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
CONTAINER_IMAGE_ORGANIZATION=${GITHUB_REPOSITORY_OWNER:-"searxng"}
|
||||||
|
CONTAINER_IMAGE_NAME="searxng"
|
||||||
|
|
||||||
|
container.build() {
|
||||||
|
pyenv.install
|
||||||
|
|
||||||
|
local parch=${OVERRIDE_ARCH:-$(uname -m)}
|
||||||
|
local container_engine
|
||||||
|
local dockerfile
|
||||||
|
local arch
|
||||||
|
local variant
|
||||||
|
local platform
|
||||||
|
|
||||||
|
# Setup arch specific
|
||||||
|
case $parch in
|
||||||
|
"X64" | "x86_64" | "amd64")
|
||||||
|
dockerfile="Dockerfile"
|
||||||
|
arch="amd64"
|
||||||
|
variant=""
|
||||||
|
platform="linux/$arch"
|
||||||
|
;;
|
||||||
|
"ARM64" | "aarch64" | "arm64")
|
||||||
|
dockerfile="Dockerfile"
|
||||||
|
arch="arm64"
|
||||||
|
variant=""
|
||||||
|
platform="linux/$arch"
|
||||||
|
;;
|
||||||
|
"ARMV7" | "armhf" | "armv7l" | "armv7")
|
||||||
|
dockerfile="armv7.dockerfile"
|
||||||
|
arch="arm"
|
||||||
|
variant="v7"
|
||||||
|
platform="linux/$arch/$variant"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err_msg "Unsupported architecture; $parch"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
info_msg "Selected platform: $platform"
|
||||||
|
|
||||||
|
# Check if podman or docker is installed
|
||||||
|
if [ "$1" = "docker" ]; then
|
||||||
|
if command -v docker &>/dev/null; then
|
||||||
|
container_engine="docker"
|
||||||
|
else
|
||||||
|
die 1 "Docker is not installed"
|
||||||
|
fi
|
||||||
|
elif [ "$1" = "podman" ]; then
|
||||||
|
if command -v podman &>/dev/null; then
|
||||||
|
container_engine="podman"
|
||||||
|
else
|
||||||
|
die 1 "Podman is not installed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# If no explicit engine is passed, prioritize podman over docker
|
||||||
|
if command -v podman &>/dev/null; then
|
||||||
|
container_engine="podman"
|
||||||
|
elif command -v docker &>/dev/null; then
|
||||||
|
container_engine="docker"
|
||||||
|
else
|
||||||
|
die 1 "Podman/Docker is not installed"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
info_msg "Selected engine: $container_engine"
|
||||||
|
|
||||||
|
# Check if git is installed
|
||||||
|
if ! command -v git &>/dev/null; then
|
||||||
|
die 1 "Git is not installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
pyenv.activate
|
||||||
|
|
||||||
|
# Check if it is a git repository
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
die 1 "This is not Git repository"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git remote get-url origin &>/dev/null; then
|
||||||
|
die 1 "There is no remote origin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is a git repository
|
||||||
|
git update-index -q --refresh
|
||||||
|
python -m searx.version freeze
|
||||||
|
eval "$(python -m searx.version)"
|
||||||
|
|
||||||
|
info_msg "Set \$VERSION_STRING: $VERSION_STRING"
|
||||||
|
info_msg "Set \$VERSION_TAG: $VERSION_TAG"
|
||||||
|
info_msg "Set \$DOCKER_TAG: $DOCKER_TAG"
|
||||||
|
info_msg "Set \$GIT_URL: $GIT_URL"
|
||||||
|
info_msg "Set \$GIT_BRANCH: $GIT_BRANCH"
|
||||||
|
|
||||||
|
if [ "$container_engine" = "podman" ]; then
|
||||||
|
params_build_builder="build --format=docker --platform=$platform --target=builder --layers --identity-label=false"
|
||||||
|
params_build="build --format=docker --platform=$platform --layers --squash-all --omit-history --identity-label=false"
|
||||||
|
else
|
||||||
|
params_build_builder="build --platform=$platform --target=builder"
|
||||||
|
params_build="build --platform=$platform --squash"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GITHUB_ACTIONS" = "true" ]; then
|
||||||
|
params_build_builder+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
|
||||||
|
params_build+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
|
||||||
|
|
||||||
|
# Tags
|
||||||
|
params_build+=" --tag=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
|
||||||
|
else
|
||||||
|
# Tags
|
||||||
|
params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:latest"
|
||||||
|
params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$DOCKER_TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
"$container_engine" $params_build_builder \
|
||||||
|
--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 -- ./dockerfiles/uwsgi.ini)" \
|
||||||
|
--tag="localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:builder" \
|
||||||
|
--file="./$dockerfile" \
|
||||||
|
.
|
||||||
|
build_msg CONTAINER "Image \"builder\" built"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
"$container_engine" $params_build \
|
||||||
|
--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)" \
|
||||||
|
--build-arg="LABEL_VCS_REF=$(git rev-parse HEAD)" \
|
||||||
|
--build-arg="LABEL_VCS_URL=$GIT_URL" \
|
||||||
|
--file="./$dockerfile" \
|
||||||
|
.
|
||||||
|
build_msg CONTAINER "Image built"
|
||||||
|
|
||||||
|
if [ "$GITHUB_ACTIONS" = "true" ]; then
|
||||||
|
"$container_engine" push "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
|
||||||
|
|
||||||
|
# Output to GHA
|
||||||
|
{
|
||||||
|
echo "version_string=$VERSION_STRING"
|
||||||
|
echo "version_tag=$VERSION_TAG"
|
||||||
|
echo "docker_tag=$DOCKER_TAG"
|
||||||
|
echo "git_url=$GIT_URL"
|
||||||
|
echo "git_branch=$GIT_BRANCH"
|
||||||
|
} >>"$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
dump_return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
container.test() {
|
||||||
|
if [ "$GITHUB_ACTIONS" != "true" ]; then
|
||||||
|
die 1 "This command is intended to be run in GitHub Actions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local parch=${OVERRIDE_ARCH:-$(uname -m)}
|
||||||
|
local arch
|
||||||
|
local variant
|
||||||
|
local platform
|
||||||
|
|
||||||
|
# Setup arch specific
|
||||||
|
case $parch in
|
||||||
|
"X64" | "x86_64" | "amd64")
|
||||||
|
arch="amd64"
|
||||||
|
variant=""
|
||||||
|
platform="linux/$arch"
|
||||||
|
;;
|
||||||
|
"ARM64" | "aarch64" | "arm64")
|
||||||
|
arch="arm64"
|
||||||
|
variant=""
|
||||||
|
platform="linux/$arch"
|
||||||
|
;;
|
||||||
|
"ARMV7" | "armhf" | "armv7l" | "armv7")
|
||||||
|
arch="arm"
|
||||||
|
variant="v7"
|
||||||
|
platform="linux/$arch/$variant"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err_msg "Unsupported architecture; $parch"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
build_msg CONTAINER "Selected platform: $platform"
|
||||||
|
|
||||||
|
# Check if podman is installed
|
||||||
|
if ! command -v podman &>/dev/null; then
|
||||||
|
die 1 "podman is not installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
|
||||||
|
|
||||||
|
name="$CONTAINER_IMAGE_NAME-$(date +%N)"
|
||||||
|
|
||||||
|
podman create --name="$name" --rm --timeout=60 --network="host" \
|
||||||
|
"ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant" >/dev/null
|
||||||
|
|
||||||
|
podman start "$name" >/dev/null
|
||||||
|
podman logs -f "$name" &
|
||||||
|
pid_logs=$!
|
||||||
|
|
||||||
|
# Wait until container is ready
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
curl -vf --max-time 5 "http://localhost:8080/healthz"
|
||||||
|
|
||||||
|
kill $pid_logs &>/dev/null || true
|
||||||
|
podman stop "$name" >/dev/null
|
||||||
|
)
|
||||||
|
dump_return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
container.push() {
|
||||||
|
if [ "$GITHUB_ACTIONS" != "true" ]; then
|
||||||
|
die 1 "This command is intended to be run in GitHub Actions"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Architectures to release
|
||||||
|
local release_archs=("amd64" "arm64" "armv7")
|
||||||
|
|
||||||
|
local archs=()
|
||||||
|
local variants=()
|
||||||
|
local platforms=()
|
||||||
|
|
||||||
|
for arch in "${release_archs[@]}"; do
|
||||||
|
case $arch in
|
||||||
|
"X64" | "x86_64" | "amd64")
|
||||||
|
archs+=("amd64")
|
||||||
|
variants+=("")
|
||||||
|
platforms+=("linux/${archs[-1]}")
|
||||||
|
;;
|
||||||
|
"ARM64" | "aarch64" | "arm64")
|
||||||
|
archs+=("arm64")
|
||||||
|
variants+=("")
|
||||||
|
platforms+=("linux/${archs[-1]}")
|
||||||
|
;;
|
||||||
|
"ARMV7" | "armv7" | "armhf" | "arm")
|
||||||
|
archs+=("arm")
|
||||||
|
variants+=("v7")
|
||||||
|
platforms+=("linux/${archs[-1]}/${variants[-1]}")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err_msg "Unsupported architecture; $arch"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if podman is installed
|
||||||
|
if ! command -v podman &>/dev/null; then
|
||||||
|
die 1 "podman is not installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Pull archs
|
||||||
|
for i in "${!archs[@]}"; do
|
||||||
|
podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Tags to release
|
||||||
|
tags=("latest")
|
||||||
|
tags+=("$DOCKER_TAG")
|
||||||
|
|
||||||
|
# Create manifests
|
||||||
|
for tag in "${tags[@]}"; do
|
||||||
|
if ! podman manifest exists "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"; then
|
||||||
|
podman manifest create "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add archs to manifest
|
||||||
|
for i in "${!archs[@]}"; do
|
||||||
|
podman manifest add \
|
||||||
|
"localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
|
||||||
|
"containers-storage:ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
podman image list
|
||||||
|
|
||||||
|
# Push manifests
|
||||||
|
for tag in "${tags[@]}"; do
|
||||||
|
build_msg CONTAINER "Pushing manifest with tag: $tag"
|
||||||
|
|
||||||
|
podman manifest push \
|
||||||
|
"localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
|
||||||
|
"docker://docker.io/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
dump_return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alias
|
||||||
|
podman.build() {
|
||||||
|
container.build podman
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alias
|
||||||
|
docker.build() {
|
||||||
|
container.build docker
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alias
|
||||||
|
docker.buildx() {
|
||||||
|
container.build docker
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user