-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDockerfile
More file actions
executable file
·283 lines (241 loc) · 9.92 KB
/
Dockerfile
File metadata and controls
executable file
·283 lines (241 loc) · 9.92 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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# syntax=docker/dockerfile:1
# Multi-stage build for optimal caching with BuildKit
# Each stage builds on the previous, with COPY . . only in the final stage
# BuildKit features: cache mounts, parallel builds, improved layer caching
# Stage 1: Base system dependencies (rarely changes)
FROM node:lts-bookworm-slim AS base
# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive \
PIP_ROOT_USER_ACTION=ignore
# Install Core & Power Tools + Docker CLI (client only)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
wget \
git \
build-essential \
software-properties-common \
python3 \
python3-pip \
python3-venv \
jq \
lsof \
openssl \
ca-certificates \
gnupg \
ripgrep fd-find fzf bat \
pandoc \
poppler-utils \
ffmpeg \
imagemagick \
graphviz \
sqlite3 \
pass \
chromium \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Install Docker CE CLI (Latest) to support API 1.44+
RUN install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce-cli && \
rm -rf /var/lib/apt/lists/*
# Install ttyd (web terminal)
RUN set -eux; \
apt-get update; \
if apt-get install -y --no-install-recommends ttyd; then \
rm -rf /var/lib/apt/lists/*; \
else \
rm -rf /var/lib/apt/lists/*; \
ARCH="$(dpkg --print-architecture)"; \
case "$ARCH" in \
amd64) TTYD_ARCH="x86_64" ;; \
arm64) TTYD_ARCH="aarch64" ;; \
*) echo "Unsupported arch for ttyd: $ARCH" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.${TTYD_ARCH}" -o /usr/local/bin/ttyd; \
chmod +x /usr/local/bin/ttyd; \
fi
# Stage 2: System CLI tools (change occasionally)
FROM base AS system-tools
# Install Go (Latest)
ARG GO_VERSION=1.23.4
RUN ARCH="$(dpkg --print-architecture)" && \
case "$ARCH" in \
amd64) GOARCH="amd64" ;; \
arm64) GOARCH="arm64" ;; \
*) echo "Unsupported arch for Go: $ARCH" >&2; exit 1 ;; \
esac && \
curl -L "https://go.dev/dl/go${GO_VERSION}.linux-${GOARCH}.tar.gz" -o go.tar.gz && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz
# Install Cloudflare Tunnel (cloudflared)
RUN ARCH=$(dpkg --print-architecture) && \
curl -L --output cloudflared.deb "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}.deb" && \
dpkg -i cloudflared.deb && \
rm cloudflared.deb
# Install GitHub CLI (gh)
RUN mkdir -p -m 755 /etc/apt/keyrings && \
wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null && \
chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
apt-get update && \
apt-get install -y gh && \
rm -rf /var/lib/apt/lists/*
# Install uv (Python tool manager)
ENV UV_INSTALL_DIR="/usr/local/bin"
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
# Stage 3: Language runtimes and package managers (change sometimes)
FROM system-tools AS runtimes
ENV BUN_INSTALL_NODE=0 \
BUN_INSTALL="/data/.bun" \
PATH="/usr/local/go/bin:/data/.bun/bin:/data/.bun/install/global/bin:$PATH"
# Install Bun
RUN curl -fsSL https://bun.sh/install | bash
# Needed by packages with native addons (e.g. better-sqlite3 during bun global installs)
RUN bun install -g node-gyp
# Python tools
RUN pip3 install ipython csvkit openpyxl python-docx pypdf botasaurus browser-use playwright --break-system-packages
# Configure QMD Persistence
ENV XDG_CACHE_HOME="/data/.cache"
# Debian aliases
RUN ln -s /usr/bin/fdfind /usr/bin/fd || true && \
ln -s /usr/bin/batcat /usr/bin/bat || true
# Stage 4: Application dependencies (package installations)
FROM runtimes AS dependencies
# OpenClaw install
ARG OPENCLAW_BETA=false
ARG OPENCLAW_VERSION=latest
ENV OPENCLAW_BETA=${OPENCLAW_BETA} \
OPENCLAW_VERSION=${OPENCLAW_VERSION} \
OPENCLAW_NO_ONBOARD=1 \
NPM_CONFIG_UNSAFE_PERM=true \
BUN_INSTALL_CACHE_DIR=/data/.bun/install/cache \
NPM_CONFIG_CACHE=/data/.npm
# Install stable authoring/deploy CLIs (changes less frequently)
RUN --mount=type=cache,id=bun-install-cache,target=/data/.bun/install/cache,sharing=locked \
bun install -g vercel @marp-team/marp-cli @tobilu/qmd
# Install AI CLIs (changes more frequently) in a separate cacheable layer
RUN --mount=type=cache,id=bun-install-cache,target=/data/.bun/install/cache,sharing=locked \
bun install -g @openai/codex @google/gemini-cli opencode-ai @steipete/summarize agent-browser clawhub && \
bun pm -g untrusted
# Install OpenClaw with npm cache mount
RUN --mount=type=cache,id=npm-cache,target=/data/.npm,sharing=locked \
if [ "$OPENCLAW_BETA" = "true" ]; then \
OPENCLAW_SPEC="openclaw@beta"; \
else \
OPENCLAW_SPEC="openclaw@${OPENCLAW_VERSION}"; \
fi && \
if ! npm view "$OPENCLAW_SPEC" >/dev/null 2>&1; then \
echo "⚠️ Version $OPENCLAW_SPEC not found on npm, falling back to openclaw@latest"; \
OPENCLAW_SPEC="openclaw@latest"; \
fi && \
npm install -g "$OPENCLAW_SPEC" && \
if command -v openclaw >/dev/null 2>&1; then \
echo "✅ openclaw binary found"; \
openclaw --version; \
else \
echo "❌ OpenClaw install failed (binary 'openclaw' not found)"; \
exit 1; \
fi
# AI Tool Suite & ClawHub
RUN (curl -fsSL https://claude.ai/install.sh | bash) || true && \
(curl -fsSL https://code.kimi.com/install.sh | bash) || true
# Stage 5: Runtime application stage (changes frequently)
FROM node:lts-bookworm-slim AS runtime
ENV DEBIAN_FRONTEND=noninteractive \
PIP_ROOT_USER_ACTION=ignore
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
build-essential \
python3 \
python3-pip \
python3-venv \
jq \
lsof \
openssl \
ca-certificates \
gnupg \
unzip \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
apt-get update; \
if apt-get install -y --no-install-recommends ttyd; then \
rm -rf /var/lib/apt/lists/*; \
else \
rm -rf /var/lib/apt/lists/*; \
ARCH="$(dpkg --print-architecture)"; \
case "$ARCH" in \
amd64) TTYD_ARCH="x86_64" ;; \
arm64) TTYD_ARCH="aarch64" ;; \
*) echo "Unsupported arch for ttyd: $ARCH" >&2; exit 1 ;; \
esac; \
curl -fsSL "https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.${TTYD_ARCH}" -o /usr/local/bin/ttyd; \
chmod +x /usr/local/bin/ttyd; \
fi
# Install Docker CE CLI (needed by sandbox-setup)
RUN install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce-cli && \
rm -rf /var/lib/apt/lists/*
ARG OPENCLAW_BETA=false
ARG OPENCLAW_VERSION=latest
ENV OPENCLAW_BETA=${OPENCLAW_BETA} \
OPENCLAW_VERSION=${OPENCLAW_VERSION} \
OPENCLAW_NO_ONBOARD=1 \
NPM_CONFIG_UNSAFE_PERM=true
RUN --mount=type=cache,target=/data/.npm \
if [ "$OPENCLAW_BETA" = "true" ]; then \
OPENCLAW_SPEC="openclaw@beta"; \
else \
OPENCLAW_SPEC="openclaw@${OPENCLAW_VERSION}"; \
fi && \
if ! npm view "$OPENCLAW_SPEC" >/dev/null 2>&1; then \
echo "⚠️ Version $OPENCLAW_SPEC not found on npm, falling back to openclaw@latest"; \
OPENCLAW_SPEC="openclaw@latest"; \
fi && \
npm install -g "$OPENCLAW_SPEC" && \
if command -v openclaw >/dev/null 2>&1; then \
echo "✅ openclaw binary found"; \
openclaw --version; \
else \
echo "❌ OpenClaw install failed (binary 'openclaw' not found)"; \
exit 1; \
fi
RUN ln -s /usr/bin/fdfind /usr/bin/fd || true && \
ln -s /usr/bin/batcat /usr/bin/bat || true
WORKDIR /app
COPY . .
RUN ln -sf /data/.claude/bin/claude /usr/local/bin/claude 2>/dev/null || true && \
ln -sf /data/.kimi/bin/kimi /usr/local/bin/kimi 2>/dev/null || true && \
ln -sf /app/scripts/openclaw-approve.sh /usr/local/bin/openclaw-approve && \
chmod +x /app/scripts/*.sh /usr/local/bin/openclaw-approve
ENV PATH="/usr/local/bin:/usr/bin:/bin:/data/.local/bin:/data/.npm-global/bin:/data/.bun/bin:/data/.bun/install/global/bin:/data/.claude/bin:/data/.kimi/bin"
EXPOSE 18789 7681
CMD ["bash", "/app/scripts/bootstrap.sh"]
# Stage 6: Final application stage (changes frequently)
FROM dependencies AS full
WORKDIR /app
# Copy everything (obeying .dockerignore)
# This is the only layer that changes on code updates
COPY . .
# Specialized symlinks and permissions
RUN ln -sf /data/.claude/bin/claude /usr/local/bin/claude 2>/dev/null || true && \
ln -sf /data/.kimi/bin/kimi /usr/local/bin/kimi 2>/dev/null || true && \
ln -sf /app/scripts/openclaw-approve.sh /usr/local/bin/openclaw-approve && \
chmod +x /app/scripts/*.sh /usr/local/bin/openclaw-approve
# ✅ FINAL PATH (important)
ENV PATH="/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin:/data/.local/bin:/data/.npm-global/bin:/data/.bun/bin:/data/.bun/install/global/bin:/data/.claude/bin:/data/.kimi/bin"
EXPOSE 18789 7681
CMD ["bash", "/app/scripts/bootstrap.sh"]