-
Notifications
You must be signed in to change notification settings - Fork 271
Expand file tree
/
Copy pathDockerfile
More file actions
263 lines (231 loc) · 11.5 KB
/
Copy pathDockerfile
File metadata and controls
263 lines (231 loc) · 11.5 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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# ============================================================
# UI Build Stages - Run in parallel with separate caches
# ============================================================
# These stages use registry cache with mode=max, which means:
# - Each stage is cached independently in the registry
# - Only stages with changed dependencies will rebuild
# - Cache mounts persist across builds for faster npm installs
# - Changes to docs/ won't invalidate config_portal or webui caches
# ============================================================
# Build Config Portal UI
FROM node:25.5.0-trixie-slim AS ui-config-portal
WORKDIR /build/config_portal/frontend
COPY config_portal/frontend/package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY config_portal/frontend ./
RUN npm run build
# Build WebUI
FROM node:25.5.0-trixie-slim AS ui-webui
WORKDIR /build/client/webui/frontend
COPY client/webui/frontend/package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY client/webui/frontend ./
RUN npm run build
# Build Documentation
FROM node:25.5.0-trixie-slim AS ui-docs
WORKDIR /build/docs
COPY docs/package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
COPY docs ./
COPY README.md ../README.md
COPY cli/__init__.py ../cli/__init__.py
RUN npm run build
# Stage to extract Node.js binaries for use in Python stages
FROM node:25.5.0-trixie-slim AS node-binaries
# ============================================================
# Python Build Stage
# ============================================================
# This stage uses registry cache with mode=max for optimal caching:
# - uv cache mount (/root/.cache/uv) speeds up package downloads
# - Lock file changes only rebuild dependency installation layer
# - Source code changes only rebuild the wheel build layer
# - Independent from UI build stages - Python changes don't rebuild UI
# ============================================================
FROM python:3.13.11-slim-trixie AS builder
# Copy Node.js 25 from the official node image - Revert to NodeSource when useful (25.5 or 26) version is available
COPY --from=node-binaries /usr/local/bin/node /usr/local/bin/node
COPY --from=node-binaries /usr/local/bin/npm /usr/local/bin/npm
COPY --from=node-binaries /usr/local/bin/npx /usr/local/bin/npx
COPY --from=node-binaries /usr/local/lib/node_modules /usr/local/lib/node_modules
# Install system dependencies and uv
# Add unstable repo with APT pinning to only upgrade libtasn1-6 (CVE-2025-13151 fix)
# Pin libc6=2.41-12+deb13u3 to fix CVE-2026-0861, CVE-2026-0915, CVE-2025-15281 (glibc vulnerabilities)
# Pin dpkg=1.22.22 to fix CVE-2026-2219 (denial of service via zstd-compressed .deb archives)
# Pin libcap2=1:2.75-10+deb13u1+b1 to fix CVE-2026-4878 (TOCTOU race condition)
# Pin sed=4.9-2+deb13u1 to fix CVE-2026-5958 (-i with --follow-symlinks)
# Pin libsystemd0/libudev1=257.13-1~deb13u1 to fix multiple systemd CVEs (CVE-2026-40223..40228 et al.)
RUN echo "deb http://deb.debian.org/debian unstable main" > /etc/apt/sources.list.d/unstable.list && \
printf "Package: *\nPin: release a=unstable\nPin-Priority: 50\n\nPackage: libtasn1-6\nPin: release a=unstable\nPin-Priority: 900\n" > /etc/apt/preferences.d/99pin-libtasn1 && \
apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
curl \
dpkg=1.22.22 \
ffmpeg=7:7.1.5-0+deb13u1 \
git \
libc6=2.41-12+deb13u3 \
libcap2=1:2.75-10+deb13u1+b1 \
libsystemd0=257.13-1~deb13u1 \
libudev1=257.13-1~deb13u1 \
libtasn1-6/unstable \
libpng16-16t64=1.6.48-1+deb13u5 \
libsqlite3-0=3.46.1-7+deb13u1 \
libssl3t64=3.5.6-1~deb13u2 \
libvpx9=1.15.0-2.1+deb13u1 \
openssl-provider-legacy=3.5.6-1~deb13u2 \
openssl=3.5.6-1~deb13u2 \
sed=4.9-2+deb13u1 && \
curl -LsSf https://astral.sh/uv/install.sh | sh && \
mv /root/.local/bin/uv /usr/local/bin/uv && \
rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unstable.list /etc/apt/preferences.d/99pin-libtasn1 && \
python3 -m venv /opt/venv && \
/opt/venv/bin/pip install --upgrade "pip==26.1.2" && \
uv pip install --system "virtualenv<21" hatch
WORKDIR /app
ENV VIRTUAL_ENV=/opt/venv
ENV UV_LINK_MODE=copy
ENV UV_COMPILE_BYTECODE=1
# Sync dependencies from lock file directly into venv (cached layer)
# This is the expensive step with 188 packages (~8s with cache, ~280MB downloads without)
# Using lock file ensures reproducible builds with exact versions
# --frozen ensures lock file isn't modified, --no-dev skips dev dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync \
--frozen \
--no-dev \
--active \
--no-install-project
# Copy Python source code and essential files (skip UI source code)
COPY src ./src
COPY cli ./cli
COPY evaluation ./evaluation
COPY templates ./templates
COPY config_portal/__init__.py ./config_portal/__init__.py
COPY config_portal/backend ./config_portal/backend
COPY .github/helper_scripts ./.github/helper_scripts
# Copy pre-built UI static assets from UI build stages
COPY --from=ui-config-portal /build/config_portal/frontend/static ./config_portal/frontend/static
COPY --from=ui-webui /build/client/webui/frontend/static ./client/webui/frontend/static
COPY --from=ui-docs /build/docs/build ./docs/build
COPY LICENSE ./LICENSE
COPY README.md ./README.md
COPY pyproject.toml ./pyproject.toml
# Build the project wheel with cache mount
# Set SAM_SKIP_UI_BUILD to skip npm builds since we already have static assets
RUN --mount=type=cache,target=/root/.cache/uv \
SAM_SKIP_UI_BUILD=true hatch build -t wheel
# Install only the wheel package (not dependencies, they're already installed)
# This is fast since all deps are already in the venv
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install /app/dist/solace_agent_mesh-*.whl
# Runtime stage
FROM python:3.13.11-slim-trixie AS runtime
ENV PYTHONUNBUFFERED=1
ENV PATH="/opt/venv/bin:$PATH"
# Build argument to control LibreOffice installation for binary artifact preview
# LibreOffice is NOT installed by default to keep image size smaller
# To enable binary artifact preview (DOCX/PPTX), set:
# docker build --build-arg INSTALL_LIBREOFFICE=true -t sam .
# Or via environment variable:
# INSTALL_LIBREOFFICE=true docker build --build-arg INSTALL_LIBREOFFICE -t sam .
#
# IMPORTANT: LibreOffice is a separate open-source application licensed under MPL-2.0.
# See THIRD_PARTY_LICENSES/LIBREOFFICE.md for full license and attribution details.
# Source code: https://www.libreoffice.org/download/source-code/
ARG INSTALL_LIBREOFFICE
# Copy Node.js 25 from the official node image
COPY --from=node-binaries /usr/local/bin/node /usr/local/bin/node
COPY --from=node-binaries /usr/local/bin/npm /usr/local/bin/npm
COPY --from=node-binaries /usr/local/bin/npx /usr/local/bin/npx
COPY --from=node-binaries /usr/local/lib/node_modules /usr/local/lib/node_modules
# Install minimal runtime dependencies (no uv for licensing compliance, no curl - due to vulnerabilities)
# LibreOffice is optionally installed for document conversion (DOCX/PPTX to PDF for preview)
# Add unstable repo with APT pinning to only upgrade libtasn1-6 (CVE-2025-13151 fix)
# Pin libc6=2.41-12+deb13u3 to fix CVE-2026-0861, CVE-2026-0915, CVE-2025-15281 (glibc vulnerabilities)
# Pin dpkg=1.22.22 to fix CVE-2026-2219 (denial of service via zstd-compressed .deb archives)
# Pin libcap2=1:2.75-10+deb13u1+b1 to fix CVE-2026-4878 (TOCTOU race condition)
# Pin sed=4.9-2+deb13u1 to fix CVE-2026-5958 (-i with --follow-symlinks)
# Pin libsystemd0/libudev1=257.13-1~deb13u1 to fix multiple systemd CVEs (CVE-2026-40223..40228 et al.)
RUN echo "deb http://deb.debian.org/debian unstable main" > /etc/apt/sources.list.d/unstable.list && \
printf "Package: *\nPin: release a=unstable\nPin-Priority: 50\n\nPackage: libtasn1-6\nPin: release a=unstable\nPin-Priority: 900\n" > /etc/apt/preferences.d/99pin-libtasn1 && \
apt-get update && \
apt-get install -y --no-install-recommends \
dpkg=1.22.22 \
ffmpeg=7:7.1.5-0+deb13u1 \
git \
libatomic1 \
libc6=2.41-12+deb13u3 \
libcap2=1:2.75-10+deb13u1+b1 \
libsystemd0=257.13-1~deb13u1 \
libudev1=257.13-1~deb13u1 \
libtasn1-6/unstable \
libpng16-16t64=1.6.48-1+deb13u5 \
libsqlite3-0=3.46.1-7+deb13u1 \
libssl3t64=3.5.6-1~deb13u2 \
libvpx9=1.15.0-2.1+deb13u1 \
openssl-provider-legacy=3.5.6-1~deb13u2 \
openssl=3.5.6-1~deb13u2 \
sed=4.9-2+deb13u1 && \
if [ "${INSTALL_LIBREOFFICE}" = "true" ]; then \
echo "============================================================" && \
echo "NOTICE: Installing LibreOffice - a separate open-source application" && \
echo "LibreOffice is licensed under Mozilla Public License 2.0 (MPL-2.0)" && \
echo "License: https://www.mozilla.org/en-US/MPL/2.0/" && \
echo "Source: https://www.libreoffice.org/download/source-code/" && \
echo "See THIRD_PARTY_LICENSES/LIBREOFFICE.md for full attribution" && \
echo "============================================================" && \
apt-get install -y --no-install-recommends \
libreoffice-writer-nogui \
libreoffice-impress-nogui \
libreoffice-calc-nogui; \
else \
echo "Skipping LibreOffice installation (set INSTALL_LIBREOFFICE=true to enable binary artifact preview)"; \
fi && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/unstable.list /etc/apt/preferences.d/99pin-libtasn1
# Node 25.5.0 ships with npm 11.8.0; upgrade to pick up security fixes in bundled dependencies
# Upgrade npm to fix CVE-2026-42338 (ip-address XSS vulnerability)
RUN node /usr/local/lib/node_modules/npm/bin/npm-cli.js install -g npm@11.15.0
# Install playwright temporarily just for browser installation (cached layer)
# This is separate from the full venv to keep this layer cached
# We'll use the playwright from the full venv at runtime
# Upgrade the base image's system pip to 26.1.2 to fix CVE-2026-3219, CVE-2026-6357, CVE-2026-8643
# (the venv pip is upgraded separately in the builder stage; the system pip ships at 25.3 otherwise)
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=cache,target=/root/.cache/playwright \
python3 -m pip install --upgrade "pip==26.1.2" && \
python3 -m pip install playwright && \
playwright install-deps chromium && \
playwright install chromium && \
python3 -m pip uninstall playwright -y
# Create non-root user and Playwright cache directory
RUN groupadd -r solaceai && useradd --create-home -r -g solaceai solaceai && \
mkdir -p /var/cache/playwright && \
chown -R solaceai:solaceai /var/cache/playwright
WORKDIR /app
RUN chown -R solaceai:solaceai /app
# Copy the pre-built virtual environment from builder
# This avoids slow pip install in runtime (UV already did it)
# Copied AFTER Playwright setup so Playwright layers stay cached
COPY --from=builder /opt/venv /opt/venv
COPY preset /preset
USER solaceai
# Required environment variables
ENV CONFIG_PORTAL_HOST=0.0.0.0
ENV FASTAPI_HOST=0.0.0.0
ENV FASTAPI_PORT=8000
ENV NAMESPACE=sam/
ENV SOLACE_DEV_MODE=True
# Set the following environment variables to appropriate values before deploying
ENV SESSION_SECRET_KEY="REPLACE_WITH_SESSION_SECRET_KEY"
LABEL org.opencontainers.image.source=https://github.com/SolaceLabs/solace-agent-mesh
EXPOSE 5002 8000
# CLI entry point
ENTRYPOINT ["solace-agent-mesh"]
# Default command to run the preset agents
CMD ["run", "/preset/agents"]