-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
218 lines (182 loc) · 8.08 KB
/
Dockerfile
File metadata and controls
218 lines (182 loc) · 8.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# syntax=docker/dockerfile:1
# Dockerfile for LFX Runtime Executor Node
# Build from repo root: docker build -f Dockerfile -t droqai/lfx-runtime-executor-node:latest .
################################
# BUILDER STAGE
# Build dependencies and Langflow
################################
FROM ghcr.io/astral-sh/uv:python3.12-alpine AS builder
# Install build dependencies
# Retry on failure to handle transient network issues
RUN set -e; \
for i in 1 2 3; do \
apk update && \
apk add --no-cache \
build-base \
libaio-dev \
linux-headers && \
break || sleep 5; \
done
WORKDIR /app
# Enable bytecode compilation
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
# Copy dependency files first (for better caching)
# Copy uv.lock file to use the same dependency resolution as local setup
COPY uv.lock /app/uv.lock
COPY pyproject.toml /app/pyproject.toml
COPY README.md /app/README.md
# Copy Langflow dependency files
COPY lfx/pyproject.toml /app/lfx/pyproject.toml
COPY lfx/README.md /app/lfx/README.md
# Copy Langflow source (needed for installation)
COPY lfx/src /app/lfx/src
# Copy executor node source
COPY src/node /app/src/node
# Create venv first
RUN --mount=type=cache,target=/root/.cache/uv \
uv venv
# Install lfx package FIRST to pin langchain-core<1.0.0 (which has langchain_core.memory)
# This ensures langchain_core.memory is available before any other packages
RUN --mount=type=cache,target=/root/.cache/uv \
cd /app/lfx && \
uv pip install --python /app/.venv/bin/python --no-cache -e .
# Explicitly pin langchain-core to <1.0.0 to prevent any upgrades
# This is critical - langchain-core>=1.0.0 doesn't have langchain_core.memory
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-core>=0.3.66,<1.0.0" --force-reinstall
# Install langchain package which provides langchain_core.memory
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain~=0.3.23"
# Now sync other dependencies from lock file (executor node dependencies)
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev || echo "Warning: Some dependencies may conflict, continuing..."
# Install the executor node package itself (editable install like local)
# Use uv pip install to install into the venv
RUN --mount=type=cache,target=/root/.cache/uv \
cd /app && \
uv pip install --python /app/.venv/bin/python --no-cache -e .
# Install langchain integration packages compatible with langchain-core<1.0.0
# Pin versions to match local working installation (langchain-core 0.3.79, pydantic 2.12.4)
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-openai==0.2.14" \
"langchain-anthropic>=0.1.13,<0.2.0" \
"langchain-community>=0.0.38,<0.1.0" \
"langchain-google-genai>=0.0.6,<0.1.0" \
"langchain-ollama>=0.3.5,<0.4.0" || echo "Warning: Some langchain packages failed to install"
# Re-pin langchain-core after installing integration packages (they might try to upgrade it)
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-core>=0.3.66,<1.0.0" --force-reinstall
# Re-install langchain package after re-pinning langchain-core (uv sync or re-pin might have removed it)
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain~=0.3.23" || echo "Warning: langchain installation failed"
# Re-install langchain-openai after re-pinning to ensure compatibility with langchain-core<1.0.0
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-openai==0.2.14" --force-reinstall || echo "Warning: langchain-openai re-installation failed"
# Ensure all lfx dependencies are installed (some might not be in the lock file)
# NOTE: aiofile and aiofiles are DIFFERENT packages - both are required!
# Also ensure langchain is installed (required by AgentComponent and other components)
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain~=0.3.23" \
"nanoid>=2.0.0,<3.0.0" \
"platformdirs>=4.3.8,<5.0.0" \
"aiofile>=3.8.0,<4.0.0" \
"aiofiles>=24.1.0,<25.0.0" \
"pillow>=10.0.0,<13.0.0" \
"emoji>=2.0.0,<3.0.0" \
"asyncer>=0.0.8,<1.0.0" \
"cachetools>=5.5.2,<6.0.0" \
"chardet>=5.2.0,<6.0.0" \
"defusedxml>=0.7.1,<1.0.0" \
"docstring-parser>=0.16,<1.0.0" \
"json-repair>=0.30.3,<1.0.0" \
"loguru>=0.7.3,<1.0.0" \
"networkx>=3.4.2,<4.0.0" \
"orjson>=3.10.15,<4.0.0" \
"passlib>=1.7.4,<2.0.0" \
"pydantic>=2.12.4,<3.0.0" \
"pydantic-settings>=2.10.1,<3.0.0" \
"rich>=13.0.0,<14.0.0" \
"tomli>=2.2.1,<3.0.0" \
"typer>=0.16.0,<1.0.0" \
"typing-extensions>=4.14.0,<5.0.0" \
"validators>=0.34.0,<1.0.0" \
"qdrant-client>=1.15.1,<2.0.0"
# Install langchain-experimental for PythonREPLComponent and other experimental features
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-experimental>=0.0.50,<1.0.0" || echo "Warning: langchain-experimental installation failed"
# Re-pin langchain-core after langchain-experimental (it might have upgraded langchain-core to >=1.0.0)
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --python /app/.venv/bin/python --no-cache \
"langchain-core>=0.3.66,<1.0.0" --force-reinstall
# Copy node.json mapping file and startup script
COPY node.json /app/node.json
COPY start-local.sh /app/start-local.sh
################################
# RUNTIME STAGE
# Minimal runtime image
################################
FROM python:3.12-alpine AS runtime
# Install runtime dependencies with retry (including bash for start-local.sh)
RUN set -e; \
for i in 1 2 3; do \
apk update && \
apk add --no-cache curl bash && \
break || sleep 5; \
done
# Create non-root user
RUN adduser -D -u 1000 -G root -h /app -s /sbin/nologin executor
WORKDIR /app
# Copy the virtual environment from builder (created by uv sync)
# This ensures all dependencies are installed exactly as in local setup
COPY --from=builder --chown=executor:root /app/.venv /app/.venv
# Copy application code
# Copy node package to /app/node (so "import node" works)
COPY --from=builder --chown=executor:root /app/src/node /app/node
COPY --from=builder --chown=executor:root /app/lfx/src /app/lfx/src
COPY --from=builder --chown=executor:root /app/node.json /node.json
COPY --from=builder --chown=executor:root /app/README.md /app/README.md
COPY --from=builder --chown=executor:root /app/pyproject.toml /app/pyproject.toml
COPY --from=builder /app/start-local.sh /app/start-local.sh
# Add venv to PATH so Python uses the venv's packages
ENV PATH="/app/.venv/bin:$PATH"
# QDRANT DOCKER NETWORKING:
# To connect to Qdrant in another Docker container:
# 1. Ensure both containers are on the same Docker network (use --network or docker-compose)
# 2. In the Qdrant component UI, set Host to the Qdrant container name "qdrant"
# instead of "localhost"
# 3. The Qdrant container name is: qdrant
#
# These ENV vars are set for future use if component code is updated to read them:
ENV QDRANT_HOST="172.17.0.3"
ENV QDRANT_PORT="6333"
ENV QDRANT_GRPC_PORT="6334"
# Make startup script executable and verify it exists (as root, before switching users)
RUN chmod +x /app/start-local.sh && \
chown executor:root /app/start-local.sh && \
ls -la /app/start-local.sh
# Set environment variables
ENV PYTHONPATH=/app:/app/lfx/src
ENV PYTHONUNBUFFERED=1
ENV HOST=0.0.0.0
ENV PORT=8000
ENV LANGFLOW_EXECUTOR_NODE_URL=http://localhost:8000
ENV DOCKER_CONTAINER=1
ENV RELOAD=false
# Switch to non-root user
USER executor
# Expose port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Run the executor node using start-local.sh
CMD ["/bin/bash", "./start-local.sh"]