Files
langflow/docker/build_and_push_base.Dockerfile
Rakshith Ramprakash e5d42e54fc feat: upgrade Firecrawl to v2 SDK and extract into the lfx-firecrawl extension bundle (#13495)
* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: add Firecrawl Search API to the bundle page

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* fix(firecrawl): D205 docstring + defensive .get('data') in crawl

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(firecrawl): D205 docstring in scrape

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* perf(firecrawl): use list.extend in map (PERF401)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: add unit tests for Firecrawl v2 components

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* test: align Firecrawl component tests with lfx _attributes pattern

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* refactor(firecrawl): remove deprecated extract endpoint component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(firecrawl): remove deprecated extract endpoint component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: drop extract component test (extract endpoint removed)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: remove Firecrawl Extract API section (deprecated)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* fix(firecrawl): map Search component to Firecrawl icon, drop Extract

The frontend icon map in styleUtils.ts still referenced the removed
FirecrawlExtractApi and lacked the new FirecrawlSearchApi, so the Search
node would not render the Firecrawl logo.

* chore: regenerate component index for Firecrawl v2 (Search added, Extract removed)

* refactor(firecrawl): extract components into the lfx-firecrawl extension bundle

Port the firecrawl provider out of lfx.components into a standalone
Extension Bundle at src/bundles/firecrawl (distribution: lfx-firecrawl),
following src/bundles/PORTING.md:

- Move the v2-SDK components (Scrape, Crawl, Map, Search) to
  src/bundles/firecrawl/src/lfx_firecrawl/components/firecrawl/ and
  remove the in-tree provider + its lfx.components registration.
- Own the firecrawl-py>=4,<5 pin in the bundle; drop it from
  langflow-base.
- Wire the workspace (root pyproject deps/sources/members) and uv.lock.
- Append migration-table entries (bare name, both import paths, pre-a
  slot) for the four classes; FirecrawlExtractApi gets no entries since
  the v2 SDK removed the extract endpoint and the component was dropped.
- Regenerate the component index (firecrawl category removed) and
  locales/en.json (54 firecrawl keys move out of core).
- Bundle-local unit tests + test_pilot_firecrawl_upgrade integration
  test; update Dockerfile bundle enumeration comments.

* fix(lfx): repair migration table entry fused during release-1.11.0 merge

The release-1.11.0 back-merge collided the FirecrawlSearchApi legacy_slot
entry with the NextPlaidVectorStoreComponent bare_class_name entry, mashing
both into a single object with duplicate 'target' keys, populating two of
{bare_class_name, import_path, legacy_slot}. That fails the MigrationTable
validator (entries.51) and broke the lfx loader tests.

Split it into the two intended entries so each populates exactly one
key-field. Restores the FirecrawlSearchApi and NextPlaidVectorStoreComponent
quads (60 entries total, +16 vs base). Append-only and bare-name guards pass.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-06-17 12:55:01 +00:00

139 lines
5.9 KiB
Docker

# syntax=docker/dockerfile:1
# Keep this syntax directive! It's used to enable Docker BuildKit
################################
# BUILDER-BASE
# Used to build deps + create our virtual environment
################################
# 1. use python:3.12.3-slim as the base image until https://github.com/pydantic/pydantic-core/issues/1292 gets resolved
# 2. do not add --platform=$BUILDPLATFORM because the pydantic binaries must be resolved for the final architecture
# Use a Python image with uv pre-installed
FROM ghcr.io/astral-sh/uv:python3.14-trixie-slim AS builder
# Install the project into `/app`
WORKDIR /app
# Enable bytecode compilation
ENV UV_COMPILE_BYTECODE=1
# Copy from the cache instead of linking since it's a mounted volume
ENV UV_LINK_MODE=copy
# Set RUSTFLAGS for reqwest unstable features needed by apify-client v2.0.0
ENV RUSTFLAGS='--cfg reqwest_unstable'
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install --no-install-recommends -y \
# deps for building python deps
build-essential \
git \
# npm
npm \
# gcc
gcc \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy files first to avoid permission issues with bind mounts
COPY ./uv.lock /app/uv.lock
COPY ./README.md /app/README.md
COPY ./pyproject.toml /app/pyproject.toml
COPY ./src/backend/base/README.md /app/src/backend/base/README.md
COPY ./src/backend/base/pyproject.toml /app/src/backend/base/pyproject.toml
# Copy lfx metadata files since it's a workspace member
COPY ./src/lfx/pyproject.toml /app/src/lfx/pyproject.toml
COPY ./src/lfx/README.md /app/src/lfx/README.md
# Copy sdk metadata files since it's a workspace member
COPY ./src/sdk/pyproject.toml /app/src/sdk/pyproject.toml
COPY ./src/sdk/README.md /app/src/sdk/README.md
# Workspace bundles (LE-1023 pilot+): every directory under ``src/bundles``
# is a uv workspace member, so each bundle's pyproject.toml must be present
# for ``uv sync --no-install-project`` to resolve the workspace. Copy the
# whole tree once rather than enumerating each bundle, so a new bundle does
# not require a Dockerfile edit.
COPY ./src/bundles /app/src/bundles
# Install the project's dependencies using the lockfile and settings
# We need to mount the root uv.lock and pyproject.toml to build the base with uv because we're still using uv workspaces
RUN --mount=type=cache,target=/root/.cache/uv \
RUSTFLAGS='--cfg reqwest_unstable' \
cd src/backend/base && uv sync --frozen --no-install-project --no-dev --no-editable --extra postgresql
COPY ./src /app/src
COPY src/frontend /tmp/src/frontend
WORKDIR /tmp/src/frontend
# Increase memory and disable concurrent builds to avoid esbuild crashes on emulated architectures
# Force esbuild to use JS implementation on emulated architectures to avoid native binary crashes
RUN npm install \
&& ESBUILD_BINARY_PATH="" NODE_OPTIONS="--max-old-space-size=4096" JOBS=1 npm run build \
&& cp -r build /app/src/backend/base/langflow/frontend \
&& rm -rf /tmp/src/frontend
WORKDIR /app/src/backend/base
# langflow-base ships the core framework only. The extension bundles
# (lfx-duckduckgo, lfx-arxiv, lfx-ibm, lfx-docling, lfx-firecrawl) are intentionally NOT
# installed in this image: they are dependencies of the full ``langflow``
# distribution, not of the lean ``langflow-base`` core, and we keep that
# boundary at the image layer too. Consumers who want those components
# should use the ``langflow`` image, or ``pip install`` the bundle (e.g.
# ``lfx-duckduckgo``) alongside langflow-base.
RUN --mount=type=cache,target=/root/.cache/uv \
RUSTFLAGS='--cfg reqwest_unstable' \
uv sync --frozen --no-dev --no-editable --extra postgresql
################################
# RUNTIME
# Setup user, utilities and copy the virtual environment only
################################
FROM python:3.14-slim-trixie AS runtime
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install --no-install-recommends -y curl git libpq5 gnupg xz-utils \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/bin/uv /usr/local/bin/uv
COPY --from=builder /usr/local/bin/uvx /usr/local/bin/uvx
RUN ARCH=$(dpkg --print-architecture) \
&& if [ "$ARCH" = "amd64" ]; then NODE_ARCH="x64"; \
elif [ "$ARCH" = "arm64" ]; then NODE_ARCH="arm64"; \
else NODE_ARCH="$ARCH"; fi \
&& NODE_VERSION=$(curl -fsSL https://nodejs.org/dist/latest-v22.x/ \
| sed -nE "s/.*node-v([0-9]+\.[0-9]+\.[0-9]+)-linux-${NODE_ARCH}\.tar\.xz.*/\1/p" \
| head -1) \
&& if [ -z "$NODE_VERSION" ]; then echo "ERROR: Could not determine Node.js version" && exit 1; fi \
&& curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" \
| tar -xJ -C /usr/local --strip-components=1
RUN useradd user -u 1000 -g 0 --no-create-home --home-dir /app/data
COPY --from=builder --chown=1000 /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
# Pre-create LANGFLOW_CONFIG_DIR (the default location used by the docker_example
# compose file) with the non-root user as owner. When the official compose mounts
# a fresh named volume at /app/langflow, Docker copies this directory's ownership
# and permissions into the new volume, so the in-container uid=1000 user can
# write secret_key, profile_pictures, etc. Without this, the volume is created
# as root:root and Langflow crashes during startup with PermissionError on
# /app/langflow/secret_key. See https://github.com/langflow-ai/langflow/issues/10437
RUN mkdir -p /app/langflow && chown -R 1000:0 /app/langflow && chmod -R g+rwX /app/langflow
LABEL org.opencontainers.image.title=langflow
LABEL org.opencontainers.image.authors=['Langflow']
LABEL org.opencontainers.image.licenses=MIT
LABEL org.opencontainers.image.url=https://github.com/langflow-ai/langflow
LABEL org.opencontainers.image.source=https://github.com/langflow-ai/langflow
USER user
WORKDIR /app
ENV LANGFLOW_HOST=0.0.0.0
ENV LANGFLOW_PORT=7860
CMD ["langflow-base", "run"]