# Backend-only DeerFlow image for offline delivery. # # Build online once, then export with: # docker save deerflow-backend-offline:latest -o deerflow-backend-offline.tar # # Runtime code/config/data are bind-mounted by start-backend-docker.sh so the # customer can edit code, agents, skills, config.yaml, .env, and SQLite data # without rebuilding this dependency image. ARG PYTHON_IMAGE=python:3.12-slim-bookworm FROM ${PYTHON_IMAGE} AS builder ARG APT_MIRROR=mirrors.aliyun.com ARG UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple/ ARG UV_VERSION=0.7.20 ARG UV_NO_CACHE=1 ARG UV_COMPILE_BYTECODE=0 ENV UV_PROJECT_ENVIRONMENT=/opt/venv \ UV_INDEX_URL=${UV_INDEX_URL} \ UV_LINK_MODE=copy \ UV_NO_CACHE=${UV_NO_CACHE} \ UV_COMPILE_BYTECODE=${UV_COMPILE_BYTECODE} \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /build/backend RUN if [ -n "${APT_MIRROR}" ]; then \ sed -i "s|deb.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources 2>/dev/null || true; \ sed -i "s|security.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources 2>/dev/null || true; \ sed -i "s|deb.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list 2>/dev/null || true; \ sed -i "s|security.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list 2>/dev/null || true; \ fi \ && apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ ca-certificates \ curl \ git \ && rm -rf /var/lib/apt/lists/* \ && python -m pip install --no-cache-dir -i "${UV_INDEX_URL}" "uv==${UV_VERSION}" ARG UV_HTTP_TIMEOUT=300 ARG UV_CONCURRENT_DOWNLOADS=4 ARG UV_CONCURRENT_INSTALLS=4 ARG UV_CONCURRENT_BUILDS=2 ENV UV_HTTP_TIMEOUT=${UV_HTTP_TIMEOUT} \ UV_CONCURRENT_DOWNLOADS=${UV_CONCURRENT_DOWNLOADS} \ UV_CONCURRENT_INSTALLS=${UV_CONCURRENT_INSTALLS} \ UV_CONCURRENT_BUILDS=${UV_CONCURRENT_BUILDS} COPY pyproject.toml uv.lock README.md requirements-offline.txt ./ COPY packages ./packages RUN python -m venv /opt/venv \ && /opt/venv/bin/python -m pip install --no-cache-dir --upgrade -i "${UV_INDEX_URL}" pip setuptools wheel \ && sed -E '/--hash=/d; s/[[:space:]]+\\$//; s|^-e[[:space:]]+./packages/harness$|./packages/harness|' requirements-offline.txt > /tmp/requirements-docker.txt \ && /opt/venv/bin/pip install --no-cache-dir -i "${UV_INDEX_URL}" -r /tmp/requirements-docker.txt \ && /opt/venv/bin/pip install --no-cache-dir -i "${UV_INDEX_URL}" \ "asyncmy>=0.2.11" \ "python-docx==1.2.0" \ && /opt/venv/bin/python -c 'import docx, lxml, mammoth, markitdown, openpyxl, pandas, pptx, xlrd; print("Office Python dependencies OK")' COPY . . FROM ${PYTHON_IMAGE} AS runtime ARG APT_MIRROR=mirrors.aliyun.com ENV PATH=/opt/venv/bin:$PATH \ PYTHONPATH=/app/backend:/app/backend/packages/harness \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ DEER_FLOW_PROJECT_ROOT=/app/backend \ DEER_FLOW_HOME=/app/backend/.deer-flow \ DEER_FLOW_CONFIG_PATH=/app/backend/config.yaml \ DEER_FLOW_EXTENSIONS_CONFIG_PATH=/app/backend/extensions_config.json \ DEER_FLOW_SKILLS_PATH=/app/backend/skills \ BACKEND_PORT=8001 WORKDIR /app/backend RUN if [ -n "${APT_MIRROR}" ]; then \ sed -i "s|deb.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources 2>/dev/null || true; \ sed -i "s|security.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources 2>/dev/null || true; \ sed -i "s|deb.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list 2>/dev/null || true; \ sed -i "s|security.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list 2>/dev/null || true; \ fi \ && apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ docker.io \ file \ fontconfig \ fonts-liberation \ fonts-noto-cjk \ libmagic1 \ libreoffice-calc \ libreoffice-impress \ libreoffice-writer \ nodejs \ npm \ pandoc \ poppler-utils \ tini \ && rm -rf /var/lib/apt/lists/* COPY --from=builder /opt/venv /opt/venv COPY --from=builder /build/backend /app/backend RUN /opt/venv/bin/python -c 'import docx, lxml, mammoth, markitdown, openpyxl, pandas, pptx, xlrd' \ && command -v soffice >/dev/null \ && command -v pandoc >/dev/null \ && fc-list :lang=zh | grep -q . EXPOSE 8001 ENTRYPOINT ["tini", "--"] CMD ["sh", "-c", "cd /app/backend && exec uvicorn app.gateway.app:app --host 0.0.0.0 --port ${BACKEND_PORT:-8001}"]