diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 6b9e2e2..af715a8 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -11,6 +11,13 @@ on: jobs: build-amd64: runs-on: ubuntu-latest + strategy: + matrix: + variant: + - name: full + dockerfile: Dockerfile + - name: standalone + dockerfile: Dockerfile.standalone steps: - name: Checkout code uses: actions/checkout@v3 @@ -31,47 +38,54 @@ jobs: id: version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Build and push AMD64 Docker image + - name: Build and push AMD64 Docker image (master) if: github.ref == 'refs/heads/master' && github.event_name == 'push' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/amd64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:amd64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-amd64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:amd64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-amd64 \ --push . - name: Build and push AMD64 Canary Docker image if: github.ref == 'refs/heads/canary' && github.event_name == 'push' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/amd64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:canary-amd64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:canary-amd64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \ --push . - name: Build and push AMD64 release Docker image if: github.event_name == 'release' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/amd64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \ --push . build-arm64: runs-on: ubuntu-24.04-arm + strategy: + matrix: + variant: + - name: full + dockerfile: Dockerfile + - name: standalone + dockerfile: Dockerfile.standalone steps: - name: Checkout code uses: actions/checkout@v3 @@ -92,48 +106,51 @@ jobs: id: version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Build and push ARM64 Docker image + - name: Build and push ARM64 Docker image (master) if: github.ref == 'refs/heads/master' && github.event_name == 'push' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/arm64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:arm64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-arm64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:arm64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-arm64 \ --push . - name: Build and push ARM64 Canary Docker image if: github.ref == 'refs/heads/canary' && github.event_name == 'push' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/arm64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:canary-arm64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:canary-arm64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 \ --push . - name: Build and push ARM64 release Docker image if: github.event_name == 'release' run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica + DOCKERFILE=${{ matrix.variant.dockerfile }} + VARIANT=${{ matrix.variant.name }} docker buildx build --platform linux/arm64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 \ + --cache-from=type=registry,ref=itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \ --cache-to=type=inline \ --provenance false \ -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 \ + -t itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 \ --push . manifest: needs: [build-amd64, build-arm64] runs-on: ubuntu-latest + strategy: + matrix: + variant: [full, standalone] steps: - name: Log in to DockerHub uses: docker/login-action@v2 @@ -146,29 +163,55 @@ jobs: id: version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Create and push multi-arch manifest for main + - name: Create and push manifest for main if: github.ref == 'refs/heads/master' && github.event_name == 'push' run: | - IMAGE_NAME=perplexica - docker manifest create itzcrazykns1337/${IMAGE_NAME}:main \ - --amend itzcrazykns1337/${IMAGE_NAME}:amd64 \ - --amend itzcrazykns1337/${IMAGE_NAME}:arm64 - docker manifest push itzcrazykns1337/${IMAGE_NAME}:main + VARIANT=${{ matrix.variant }} + docker manifest create itzcrazykns1337/perplexica:${VARIANT}-latest \ + --amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-arm64 + docker manifest push itzcrazykns1337/perplexica:${VARIANT}-latest - - name: Create and push multi-arch manifest for canary + if [ "$VARIANT" = "full" ]; then + docker manifest create itzcrazykns1337/perplexica:latest \ + --amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-arm64 + docker manifest push itzcrazykns1337/perplexica:latest + + docker manifest create itzcrazykns1337/perplexica:main \ + --amend itzcrazykns1337/perplexica:${VARIANT}-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-arm64 + docker manifest push itzcrazykns1337/perplexica:main + fi + + - name: Create and push manifest for canary if: github.ref == 'refs/heads/canary' && github.event_name == 'push' run: | - IMAGE_NAME=perplexica - docker manifest create itzcrazykns1337/${IMAGE_NAME}:canary \ - --amend itzcrazykns1337/${IMAGE_NAME}:canary-amd64 \ - --amend itzcrazykns1337/${IMAGE_NAME}:canary-arm64 - docker manifest push itzcrazykns1337/${IMAGE_NAME}:canary + VARIANT=${{ matrix.variant }} + docker manifest create itzcrazykns1337/perplexica:${VARIANT}-canary \ + --amend itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 + docker manifest push itzcrazykns1337/perplexica:${VARIANT}-canary - - name: Create and push multi-arch manifest for releases + if [ "$VARIANT" = "full" ]; then + docker manifest create itzcrazykns1337/perplexica:canary \ + --amend itzcrazykns1337/perplexica:${VARIANT}-canary-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-canary-arm64 + docker manifest push itzcrazykns1337/perplexica:canary + fi + + - name: Create and push manifest for releases if: github.event_name == 'release' run: | - IMAGE_NAME=perplexica - docker manifest create itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }} \ - --amend itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ - --amend itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 - docker manifest push itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }} + VARIANT=${{ matrix.variant }} + docker manifest create itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }} \ + --amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 + docker manifest push itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }} + + if [ "$VARIANT" = "full" ]; then + docker manifest create itzcrazykns1337/perplexica:${{ env.RELEASE_VERSION }} \ + --amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-amd64 \ + --amend itzcrazykns1337/perplexica:${VARIANT}-${{ env.RELEASE_VERSION }}-arm64 + docker manifest push itzcrazykns1337/perplexica:${{ env.RELEASE_VERSION }} + fi diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b219660 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,74 @@ +FROM node:24.5.0-slim AS builder + +RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/* + +WORKDIR /home/perplexica + +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --network-timeout 600000 + +COPY tsconfig.json next.config.mjs next-env.d.ts postcss.config.js drizzle.config.ts tailwind.config.ts ./ +COPY src ./src +COPY public ./public +COPY drizzle ./drizzle + +RUN mkdir -p /home/perplexica/data +RUN yarn build + +FROM node:24.5.0-slim + +RUN apt-get update && \ + apt-get install -y \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + sqlite3 \ + git \ + build-essential \ + libxslt-dev \ + zlib1g-dev \ + libffi-dev \ + libssl-dev \ + uwsgi \ + uwsgi-plugin-python3 \ + curl \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /home/perplexica + +COPY --from=builder /home/perplexica/public ./public +COPY --from=builder /home/perplexica/.next/static ./public/_next/static +COPY --from=builder /home/perplexica/.next/standalone ./ +COPY --from=builder /home/perplexica/data ./data +COPY drizzle ./drizzle + +RUN mkdir /home/perplexica/uploads + +RUN useradd --system --home-dir /usr/local/searxng --shell /bin/sh searxng + +WORKDIR /usr/local/searxng +RUN git clone https://github.com/searxng/searxng.git . && \ + python3 -m venv venv && \ + . venv/bin/activate && \ + pip install --upgrade pip setuptools wheel pyyaml && \ + pip install -r requirements.txt && \ + pip install uwsgi + +RUN mkdir -p /etc/searxng +COPY searxng/settings.yml /etc/searxng/settings.yml +COPY searxng/limiter.toml /etc/searxng/limiter.toml +COPY searxng/uwsgi.ini /etc/searxng/uwsgi.ini + +RUN chown -R searxng:searxng /usr/local/searxng /etc/searxng + +WORKDIR /home/perplexica +COPY entrypoint.sh ./entrypoint.sh +RUN chmod +x ./entrypoint.sh +RUN sed -i 's/\r$//' ./entrypoint.sh || true + +EXPOSE 3000 8080 + +ENV SEARXNG_API_URL=http://localhost:8080 + +CMD ["/home/perplexica/entrypoint.sh"] diff --git a/Dockerfile.standalone b/Dockerfile.standalone new file mode 100644 index 0000000..d44dea4 --- /dev/null +++ b/Dockerfile.standalone @@ -0,0 +1,35 @@ +FROM node:24.5.0-slim AS builder + +RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/* + +WORKDIR /home/perplexica + +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --network-timeout 600000 + +COPY tsconfig.json next.config.mjs next-env.d.ts postcss.config.js drizzle.config.ts tailwind.config.ts ./ +COPY src ./src +COPY public ./public +COPY drizzle ./drizzle + +RUN mkdir -p /home/perplexica/data +RUN yarn build + +FROM node:24.5.0-slim + +RUN apt-get update && apt-get install -y python3 python3-pip sqlite3 && rm -rf /var/lib/apt/lists/* + +WORKDIR /home/perplexica + +COPY --from=builder /home/perplexica/public ./public +COPY --from=builder /home/perplexica/.next/static ./public/_next/static + +COPY --from=builder /home/perplexica/.next/standalone ./ +COPY --from=builder /home/perplexica/data ./data +COPY drizzle ./drizzle + +RUN mkdir /home/perplexica/uploads + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index f511e94..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,35 +0,0 @@ -services: - searxng: - image: docker.io/searxng/searxng:latest - volumes: - - ./searxng:/etc/searxng:rw - ports: - - 4000:8080 - networks: - - perplexica-network - restart: unless-stopped - - app: - image: itzcrazykns1337/perplexica:main - build: - context: . - dockerfile: app.dockerfile - environment: - - DOCKER=true - - SEARXNG_API_URL=http://searxng:8080 - - DATA_DIR=/home/perplexica - ports: - - 3000:3000 - networks: - - perplexica-network - volumes: - - backend-dbstore:/home/perplexica/data - - uploads:/home/perplexica/uploads - restart: unless-stopped - -networks: - perplexica-network: - -volumes: - backend-dbstore: - uploads: diff --git a/entrypoint.sh b/entrypoint.sh index 113a131..48ee169 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,4 +1,24 @@ #!/bin/sh set -e +cd /usr/local/searxng +export SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml + +# Start SearXNG in background with all output redirected to /dev/null +/usr/local/searxng/venv/bin/uwsgi \ + --http-socket 0.0.0.0:8080 \ + --ini /etc/searxng/uwsgi.ini \ + --virtualenv /usr/local/searxng/venv \ + --disable-logging > /dev/null 2>&1 & + +echo "Starting SearXNG..." +sleep 5 + +until curl -s http://localhost:8080 > /dev/null 2>&1; do + sleep 1 +done +echo "SearXNG started successfully" + +cd /home/perplexica +echo "Starting Perplexica..." exec node server.js \ No newline at end of file