WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
# Temporary offline build stage: reuse the migration binary already present in
|
||||
# the last production image when the Go proxy is unavailable.
|
||||
FROM yawan-api:public-20260921-053200 AS migrate-prebuilt
|
||||
|
||||
# Build stage
|
||||
FROM golang:1.26-bookworm AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 通过构建参数接收敏感信息
|
||||
ARG GOPRIVATE_ARG
|
||||
ARG GOPROXY_ARG
|
||||
ARG GOSUMDB_ARG=off
|
||||
ARG APK_MIRROR_ARG
|
||||
|
||||
# 设置Go环境变量
|
||||
ENV GOPRIVATE=${GOPRIVATE_ARG}
|
||||
ENV GOPROXY=${GOPROXY_ARG}
|
||||
ENV GOSUMDB=${GOSUMDB_ARG}
|
||||
|
||||
# Install dependencies
|
||||
RUN if [ -n "$APK_MIRROR_ARG" ]; then \
|
||||
sed -i "s@deb.debian.org@${APK_MIRROR_ARG}@g" /etc/apt/sources.list.d/debian.sources; \
|
||||
fi && \
|
||||
apt-get update && \
|
||||
apt-get install -y git build-essential libsqlite3-dev curl
|
||||
|
||||
# Install migrate tool. The prebuilt binary keeps release builds working when
|
||||
# the public Go proxy is temporarily unreachable.
|
||||
COPY --from=migrate-prebuilt /usr/local/bin/migrate /go/bin/migrate
|
||||
|
||||
# Copy go mod files. go.mod replace-points anydoc at ./third_party/anydoc-go,
|
||||
# so that module's go.mod must exist before `go mod download`.
|
||||
COPY go.mod go.sum ./
|
||||
COPY third_party/anydoc-go/go.mod third_party/anydoc-go/go.mod
|
||||
RUN go mod download
|
||||
COPY cmd/download cmd/download
|
||||
RUN go run cmd/download/duckdb/duckdb.go
|
||||
COPY . .
|
||||
|
||||
# Get version and commit info for build injection
|
||||
ARG VERSION_ARG
|
||||
ARG COMMIT_ID_ARG
|
||||
ARG BUILD_TIME_ARG
|
||||
ARG GO_VERSION_ARG
|
||||
|
||||
# Set build-time variables
|
||||
ENV VERSION=${VERSION_ARG}
|
||||
ENV COMMIT_ID=${COMMIT_ID_ARG}
|
||||
ENV BUILD_TIME=${BUILD_TIME_ARG}
|
||||
ENV GO_VERSION=${GO_VERSION_ARG}
|
||||
|
||||
# Link the anydoc parser engine (office docs converted in-process, no
|
||||
# Python docreader). Default on so Hub / compose images ship a working
|
||||
# engine; pass WITH_ANYDOC=0 to skip the Rust toolchain (~few minutes and
|
||||
# ~1 GB of build-stage layers).
|
||||
ARG WITH_ANYDOC=1
|
||||
ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo
|
||||
ENV PATH=/usr/local/cargo/bin:$PATH
|
||||
RUN if [ "$WITH_ANYDOC" = "1" ]; then \
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||
| sh -s -- -y --profile minimal --default-toolchain stable && \
|
||||
./scripts/build-anydoc-lib.sh; \
|
||||
fi
|
||||
|
||||
# Build the application with version info
|
||||
RUN if [ "$WITH_ANYDOC" = "1" ]; then \
|
||||
make build-prod GO_BUILD_TAGS=anydoc; \
|
||||
else \
|
||||
make build-prod; \
|
||||
fi
|
||||
RUN cp -r /go/pkg/mod/github.com/yanyiwu/ /app/yanyiwu/
|
||||
|
||||
# Final stage
|
||||
FROM debian:12.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ARG APK_MIRROR_ARG
|
||||
|
||||
# Create a non-root user first
|
||||
RUN useradd -m -s /bin/bash appuser
|
||||
|
||||
# First, install ca-certificates without mirror to ensure HTTPS works
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Then switch to mirror if specified and install other packages
|
||||
RUN if [ -n "$APK_MIRROR_ARG" ]; then \
|
||||
sed -i "s@deb.debian.org@${APK_MIRROR_ARG}@g" /etc/apt/sources.list.d/debian.sources; \
|
||||
fi && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential postgresql-client default-mysql-client tzdata sed curl bash vim wget \
|
||||
libsqlite3-0 \
|
||||
python3 python3-pip python3-dev libffi-dev libssl-dev \
|
||||
nodejs npm \
|
||||
gosu \
|
||||
ffmpeg && \
|
||||
python3 -m pip install --break-system-packages --upgrade pip setuptools wheel && \
|
||||
mkdir -p /home/appuser/.local/bin && \
|
||||
curl -LsSf https://astral.sh/uv/install.sh | CARGO_HOME=/home/appuser/.cargo UV_INSTALL_DIR=/home/appuser/.local/bin sh && \
|
||||
chown -R appuser:appuser /home/appuser && \
|
||||
ln -sf /home/appuser/.local/bin/uvx /usr/local/bin/uvx && \
|
||||
chmod +x /usr/local/bin/uvx && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create data directories and set permissions
|
||||
RUN mkdir -p /data/files && \
|
||||
chown -R appuser:appuser /app /data/files
|
||||
|
||||
# Copy migrate tool from builder stage
|
||||
COPY --from=builder /go/bin/migrate /usr/local/bin/
|
||||
COPY --from=builder /app/yanyiwu/ /go/pkg/mod/github.com/yanyiwu/
|
||||
|
||||
# Copy the binary from the builder stage
|
||||
COPY --from=builder /app/config ./config
|
||||
COPY --from=builder /app/scripts ./scripts
|
||||
COPY --from=builder /app/migrations ./migrations
|
||||
COPY --from=builder /app/dataset/samples ./dataset/samples
|
||||
COPY --from=builder /app/skills/preloaded ./skills/preloaded
|
||||
# Keep a read-only backup so bind-mount cannot erase built-in skills
|
||||
COPY --from=builder /app/skills/preloaded ./skills/_builtin
|
||||
COPY --from=builder /root/.duckdb /home/appuser/.duckdb
|
||||
COPY --from=builder /app/WeKnora .
|
||||
|
||||
# Copy and make entrypoint script executable
|
||||
COPY --from=builder /app/scripts/docker-entrypoint.sh ./scripts/docker-entrypoint.sh
|
||||
|
||||
# Make scripts executable
|
||||
RUN chmod +x ./scripts/*.sh
|
||||
|
||||
# Expose ports
|
||||
EXPOSE 8080
|
||||
|
||||
|
||||
ENTRYPOINT ["./scripts/docker-entrypoint.sh"]
|
||||
CMD ["./WeKnora"]
|
||||
@@ -0,0 +1,159 @@
|
||||
# =========================
|
||||
# 构建阶段(轻量化:仅文档解析 + 图片提取,无 OCR/VLM)
|
||||
# =========================
|
||||
FROM python:3.10.18-bookworm AS builder
|
||||
|
||||
ARG APT_MIRROR=""
|
||||
RUN if [ -n "$APT_MIRROR" ]; then \
|
||||
sed -i "s@http://deb.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list.d/debian.sources && \
|
||||
sed -i "s@http://security.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list.d/debian.sources; \
|
||||
fi
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装构建依赖
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
python3-dev \
|
||||
libjpeg-dev \
|
||||
zlib1g-dev \
|
||||
libffi-dev \
|
||||
libgl1 \
|
||||
libglib2.0-0 \
|
||||
wget \
|
||||
antiword \
|
||||
curl \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 检查是否存在本地protoc安装包,如果存在则离线安装,否则在线安装
|
||||
ARG TARGETARCH
|
||||
COPY packages/ /app/packages/
|
||||
RUN ls -lah /app/packages/
|
||||
# 兼容 BuildKit 和传统构建:如果 TARGETARCH 为空,使用 uname 检测
|
||||
RUN if [ -z "$TARGETARCH" ]; then \
|
||||
case $(uname -m) in \
|
||||
"x86_64") TARGETARCH="amd64" ;; \
|
||||
"aarch64") TARGETARCH="arm64" ;; \
|
||||
"armv7l") TARGETARCH="arm" ;; \
|
||||
*) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \
|
||||
esac; \
|
||||
echo "[自动检测] 架构: $TARGETARCH"; \
|
||||
else \
|
||||
echo "[BuildKit] 架构: $TARGETARCH"; \
|
||||
fi && \
|
||||
case $TARGETARCH in \
|
||||
"amd64") PROTOC_ARCH="x86_64" ;; \
|
||||
"arm64") PROTOC_ARCH="aarch_64" ;; \
|
||||
"arm") PROTOC_ARCH="arm" ;; \
|
||||
*) echo "Unsupported architecture for protoc: $TARGETARCH" && exit 1 ;; \
|
||||
esac && \
|
||||
PROTOC_PACKAGE="protoc-3.19.4-linux-${PROTOC_ARCH}.zip" && \
|
||||
if [ -f "/app/packages/${PROTOC_PACKAGE}" ]; then \
|
||||
echo "发现本地protoc安装包,将进行离线安装"; \
|
||||
cp /app/packages/${PROTOC_PACKAGE} /app/ && \
|
||||
unzip -o /app/${PROTOC_PACKAGE} -d /usr/local && \
|
||||
chmod +x /usr/local/bin/protoc && \
|
||||
rm -f /app/${PROTOC_PACKAGE}; \
|
||||
else \
|
||||
echo "未发现本地protoc安装包,将进行在线安装"; \
|
||||
curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.19.4/${PROTOC_PACKAGE} && \
|
||||
unzip -o ${PROTOC_PACKAGE} -d /usr/local && \
|
||||
chmod +x /usr/local/bin/protoc && \
|
||||
rm -f ${PROTOC_PACKAGE}; \
|
||||
fi
|
||||
|
||||
# 复制依赖文件
|
||||
COPY docreader/pyproject.toml docreader/uv.lock ./
|
||||
RUN pip install uv --break-system-packages && \
|
||||
python -m uv sync --locked --no-dev
|
||||
|
||||
# 复制源代码和生成脚本
|
||||
COPY docreader docreader
|
||||
|
||||
# 生成 protobuf 代码(使用 venv 中的 grpc_tools)
|
||||
ENV PATH="/app/.venv/bin:${PATH}"
|
||||
RUN chmod +x docreader/scripts/generate_proto.sh && \
|
||||
bash docreader/scripts/generate_proto.sh
|
||||
|
||||
# =========================
|
||||
# 运行阶段(轻量化)
|
||||
# =========================
|
||||
FROM python:3.10.18-bookworm AS runner
|
||||
|
||||
ARG APT_MIRROR=""
|
||||
RUN if [ -n "$APT_MIRROR" ]; then \
|
||||
sed -i "s@http://deb.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list.d/debian.sources && \
|
||||
sed -i "s@http://security.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list.d/debian.sources; \
|
||||
fi
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装运行时依赖(已移除 OCR/PaddleOCR 相关依赖)
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libjpeg62-turbo \
|
||||
wget \
|
||||
gnupg \
|
||||
openjdk-17-jre-headless \
|
||||
libgl1 \
|
||||
libglib2.0-0 \
|
||||
antiword \
|
||||
tar \
|
||||
dpkg \
|
||||
libxinerama1 \
|
||||
libfontconfig1 \
|
||||
libdbus-glib-1-2 \
|
||||
libcairo2 \
|
||||
libcups2 \
|
||||
libglu1-mesa \
|
||||
libsm6 \
|
||||
libreoffice \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 安装 grpc_health_probe
|
||||
ARG TARGETARCH
|
||||
# 兼容 BuildKit 和传统构建:如果 TARGETARCH 为空,使用 uname 检测
|
||||
RUN if [ -z "$TARGETARCH" ]; then \
|
||||
case $(uname -m) in \
|
||||
"x86_64") TARGETARCH="amd64" ;; \
|
||||
"aarch64") TARGETARCH="arm64" ;; \
|
||||
"armv7l") TARGETARCH="arm" ;; \
|
||||
*) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \
|
||||
esac; \
|
||||
echo "[自动检测] 架构: $TARGETARCH"; \
|
||||
else \
|
||||
echo "[BuildKit] 架构: $TARGETARCH"; \
|
||||
fi && \
|
||||
GRPC_HEALTH_PROBE_VERSION=v0.4.24 && \
|
||||
case $TARGETARCH in \
|
||||
"amd64") ARCH="amd64" ;; \
|
||||
"arm64") ARCH="arm64" ;; \
|
||||
"arm") ARCH="arm" ;; \
|
||||
*) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
|
||||
esac && \
|
||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-${ARCH} && \
|
||||
chmod +x /bin/grpc_health_probe
|
||||
|
||||
# 从构建阶段复制已安装的依赖和生成的代码
|
||||
ENV VIRTUAL_ENV=/app/.venv
|
||||
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
|
||||
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
|
||||
|
||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||
|
||||
# 安装 Playwright 浏览器(网页解析)
|
||||
RUN python -m playwright install webkit
|
||||
RUN python -m playwright install-deps webkit
|
||||
|
||||
COPY docreader/pyproject.toml docreader/uv.lock ./
|
||||
COPY --from=builder /app/docreader docreader
|
||||
|
||||
# 创建共享临时图片目录
|
||||
RUN mkdir -p /tmp/docreader
|
||||
|
||||
# 暴露 gRPC 端口
|
||||
EXPOSE 50051
|
||||
|
||||
# 直接运行 Python 服务(日志输出到 stdout/stderr)
|
||||
CMD ["uv", "run", "-m", "docreader.main"]
|
||||
@@ -0,0 +1,29 @@
|
||||
# OpenDataLoader PDF hybrid backend (Docling). Pre-install deps so the
|
||||
# container listens on :5002 immediately instead of pip install on every start.
|
||||
#
|
||||
# Default --no-ocr: digital PDFs already have a text layer; Docling layout/table
|
||||
# still runs without EasyOCR (avoids libGL + heavy OCR stack in slim images).
|
||||
# For scanned PDFs use builtin docreader OCR, MinerU, or override with
|
||||
# ODL_HYBRID_EXTRA_ARGS="--force-ocr" (requires extra system/Python deps).
|
||||
FROM python:3.10.18-bookworm
|
||||
|
||||
# Docling table/layout models import cv2 (OpenCV), which needs libGL at runtime
|
||||
# even when hybrid runs with --no-ocr.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
libgl1 \
|
||||
libglib2.0-0 \
|
||||
libgomp1 \
|
||||
libsm6 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install --no-cache-dir "opendataloader-pdf[hybrid]>=2.4.7"
|
||||
|
||||
EXPOSE 5002
|
||||
|
||||
ENV ODL_HYBRID_EXTRA_ARGS="--no-ocr"
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=120s \
|
||||
CMD curl -f http://localhost:5002/health || exit 1
|
||||
|
||||
CMD ["bash", "-c", "exec opendataloader-pdf-hybrid --host 0.0.0.0 --port 5002 ${ODL_HYBRID_EXTRA_ARGS}"]
|
||||
@@ -0,0 +1,100 @@
|
||||
# WeKnora Sandbox Image
|
||||
# Pre-built environment for executing agent skill scripts in Docker sandbox
|
||||
# Multi-stage build, minimal dependencies
|
||||
#
|
||||
# Two targets ship from this file:
|
||||
# runtime (default) - the plain environment. Used by the Docker backend and
|
||||
# as the base image of E2B templates, whose builder
|
||||
# injects its own envd.
|
||||
# cube - the same environment plus Cube's envd daemon. Cube
|
||||
# builds templates straight from the image and probes
|
||||
# :49983/health, so an image without envd can only ever
|
||||
# fail. See docs/sandbox-cluster.md.
|
||||
|
||||
# Stage 1: Get Node.js binaries
|
||||
FROM node:20-slim AS node-base
|
||||
|
||||
# Stage 2: Runtime image
|
||||
FROM python:3.11-slim AS runtime
|
||||
|
||||
# Copy Node.js from node image (avoids NodeSource install overhead)
|
||||
COPY --from=node-base /usr/local/bin/node /usr/local/bin/
|
||||
COPY --from=node-base /usr/local/lib/node_modules /usr/local/lib/node_modules
|
||||
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
||||
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
|
||||
|
||||
# Python package manager: uv (fast pip replacement). Preinstalled because each
|
||||
# skill gets its own venv at install time, and building that from a cold pip is
|
||||
# what dominates an install's wall clock.
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.12.4 /uv /usr/local/bin/uv
|
||||
RUN ln -s /usr/local/bin/uv /usr/local/bin/uvx
|
||||
|
||||
# Node package manager: pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install minimal CLI tools (bash/grep/sed/coreutils/findutils already in slim
|
||||
# image). `file` is not in slim; models reach for it after a script-type error.
|
||||
# curl is not optional: the sandbox connectivity check probes egress with it,
|
||||
# and skills that fetch a URL expect it to be there. The compression tools are
|
||||
# here because skill bundles and their assets arrive archived.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
jq \
|
||||
curl \
|
||||
ca-certificates \
|
||||
file \
|
||||
zip \
|
||||
unzip \
|
||||
bzip2 \
|
||||
xz-utils \
|
||||
zstd \
|
||||
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
# Note: Current preloaded skills only use Python stdlib
|
||||
# Add packages here when skills actually need them:
|
||||
|
||||
# Create non-root user (UID 1000) for sandbox execution. The account is named
|
||||
# "user" because that is the account name E2B templates are expected to expose
|
||||
# and the one WeKnora names when running scripts and file operations against an
|
||||
# E2B-protocol backend; the Docker backend addresses it numerically as
|
||||
# 1000:1000, so both paths land on the same account.
|
||||
RUN groupadd -g 1000 user && \
|
||||
useradd -u 1000 -g user -m -s /bin/bash user
|
||||
|
||||
# Pre-create the two directories every backend writes to and hand them to the
|
||||
# sandbox account. WeKnora otherwise has to create and chown them as root on
|
||||
# each execution, which needs capabilities a hardened container should not
|
||||
# have to keep.
|
||||
RUN mkdir -p /workspace/input /workspace/output && \
|
||||
chown -R user:user /workspace
|
||||
|
||||
WORKDIR /workspace
|
||||
USER user
|
||||
|
||||
# Stage 3: Cube template image
|
||||
#
|
||||
# envd is what Cube talks to for everything — the readiness probe that decides
|
||||
# whether a template build succeeds, plus every later exec and file call. It
|
||||
# runs as root and drops to the account named in each request, which is why
|
||||
# this variant does not keep the runtime's USER user.
|
||||
#
|
||||
# This target is linux/amd64 only: cubesandbox-base publishes no arm64 image,
|
||||
# which matches Cube itself (PVM is x86_64-only).
|
||||
FROM ghcr.io/tencentcloud/cubesandbox-base:2026.16 AS cube-base
|
||||
|
||||
FROM runtime AS cube
|
||||
|
||||
USER root
|
||||
COPY --from=cube-base /usr/bin/envd /usr/bin/envd
|
||||
COPY --from=cube-base /usr/local/bin/cube-entrypoint.sh /usr/local/bin/cube-entrypoint.sh
|
||||
|
||||
EXPOSE 49983
|
||||
# The entrypoint backgrounds envd and then waits on it, since this image
|
||||
# defines no CMD of its own.
|
||||
ENTRYPOINT ["/usr/local/bin/cube-entrypoint.sh"]
|
||||
|
||||
# Stage 4: default target
|
||||
#
|
||||
# Docker builds the last stage when none is named, and that must stay the plain
|
||||
# runtime: a bare `docker build -f docker/Dockerfile.sandbox .` is expected to
|
||||
# produce the image the Docker backend runs, not the Cube variant.
|
||||
FROM runtime AS sandbox
|
||||
@@ -0,0 +1,31 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/var/log/supervisord.log
|
||||
logfile_maxbytes=50MB
|
||||
logfile_backups=10
|
||||
loglevel=info
|
||||
pidfile=/var/run/supervisord.pid
|
||||
user=root
|
||||
|
||||
[program:WeKnora]
|
||||
command=/app/WeKnora
|
||||
directory=/app
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=5
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/WeKnora.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stdout_logfile_backups=10
|
||||
environment=CGO_ENABLED=1
|
||||
user=appuser
|
||||
|
||||
[unix_http_server]
|
||||
file=/var/run/supervisor.sock
|
||||
chmod=0700
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///var/run/supervisor.sock
|
||||
@@ -0,0 +1,49 @@
|
||||
use_default_settings: true
|
||||
|
||||
general:
|
||||
instance_name: "WeKnora SearXNG"
|
||||
privacypolicy_url: false
|
||||
donation_url: false
|
||||
contact_url: false
|
||||
enable_metrics: false
|
||||
|
||||
server:
|
||||
# Override via env SEARXNG_SECRET; the entrypoint script substitutes ultrasecretkey.
|
||||
secret_key: "ultrasecretkey"
|
||||
base_url: false
|
||||
image_proxy: true
|
||||
http_protocol_version: "1.0"
|
||||
method: "GET"
|
||||
# Disabled so WeKnora's backend can call /search without IP-based throttling.
|
||||
# Re-enable and add WeKnora's egress IP to a limiter allowlist if you expose
|
||||
# this instance to the public internet.
|
||||
limiter: false
|
||||
public_instance: false
|
||||
|
||||
ui:
|
||||
static_use_hash: true
|
||||
default_locale: ""
|
||||
query_in_title: false
|
||||
infinite_scroll: false
|
||||
center_alignment: false
|
||||
theme_args:
|
||||
simple_style: auto
|
||||
search_on_category_select: true
|
||||
hotkeys: default
|
||||
|
||||
search:
|
||||
safe_search: 0
|
||||
autocomplete: ""
|
||||
default_lang: "auto"
|
||||
ban_time_on_fail: 5
|
||||
max_ban_time_on_fail: 120
|
||||
formats:
|
||||
- html
|
||||
- json
|
||||
|
||||
outgoing:
|
||||
request_timeout: 6.0
|
||||
max_request_timeout: 10.0
|
||||
pool_connections: 100
|
||||
pool_maxsize: 20
|
||||
enable_http2: true
|
||||
Reference in New Issue
Block a user