Skip to content

Commit ec9ded2

Browse files
fix(ticket-030): rewrite Dockerfile.openclaw with oven/bun base, fnm, node 24, openclaw cli
- Base image: oven/bun:latest (Debian-based) - Install fnm and use it to install Node.js 24 as default - Install sqlite3, cron, coreutils (nproc), tini - Install openclaw globally via npm - CMD: activate fnm + node 24, then run openclaw gateway
1 parent 784e149 commit ec9ded2

1 file changed

Lines changed: 30 additions & 123 deletions

File tree

docker/Dockerfile.openclaw

Lines changed: 30 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,45 @@
1-
# OpenClaw Gateway — Development Dockerfile
1+
# OpenClaw Gateway — Docker Image
22
#
3-
# This image provides the OpenClaw gateway runtime environment for development.
4-
# It includes a lightweight gateway stub that responds to /health and serves
5-
# the config UI on port 18789.
6-
#
7-
# In production this is replaced with the real `openclaw/pod` image.
3+
# Base: oven/bun (Debian-based)
4+
# Node.js 24 installed via fnm
5+
# Includes: sqlite, cron, nproc
86
#
97
# Usage:
108
# docker build -f docker/Dockerfile.openclaw -t openclaw/pod:latest .
119
#
1210
# Or via docker-compose (automatic):
1311
# OPENCLAW_DATA_DIR=~/.openclaw docker compose -f docker/docker-compose.openclaw.yml up -d
1412

15-
FROM node:20-alpine
16-
17-
# Install runtime dependencies
18-
RUN apk add --no-cache \
19-
curl \
20-
tini
21-
22-
# Create non-root user for the gateway
23-
RUN addgroup -g 1001 openclaw && \
24-
adduser -u 1001 -G openclaw -s /bin/sh -D openclaw
25-
26-
# Set working directory
27-
WORKDIR /home/openclaw
28-
29-
# Create gateway stub
30-
RUN mkdir -p /home/openclaw/.openclaw && \
31-
cat > /home/openclaw/gateway.js << 'GATEWAY_EOF'
32-
const http = require('http');
33-
const fs = require('fs');
34-
const path = require('path');
35-
36-
const PORT = parseInt(process.env.GATEWAY_PORT, 10) || 18789;
37-
const DATA_DIR = '/home/openclaw/.openclaw';
38-
const CONFIG_FILE = path.join(DATA_DIR, 'openclaw.json');
39-
40-
// Ensure config exists
41-
function ensureConfig() {
42-
try {
43-
if (!fs.existsSync(CONFIG_FILE)) {
44-
const cfg = {
45-
gateway: { host: '127.0.0.1', port: PORT },
46-
agents: { defaults: { model: { primary: 'anthropic/claude-sonnet-4-20250514' } } },
47-
models: { providers: {} }
48-
};
49-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
50-
}
51-
} catch (e) {
52-
console.error('Failed to write config:', e.message);
53-
}
54-
}
55-
56-
function readConfig() {
57-
try {
58-
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
59-
} catch {
60-
return { gateway: { host: '127.0.0.1', port: PORT } };
61-
}
62-
}
63-
64-
const server = http.createServer((req, res) => {
65-
res.setHeader('Content-Type', 'application/json');
66-
res.setHeader('Access-Control-Allow-Origin', '*');
67-
68-
if (req.method === 'GET' && req.url === '/health') {
69-
res.writeHead(200);
70-
res.end(JSON.stringify({
71-
status: 'ok',
72-
port: PORT,
73-
uptime: process.uptime(),
74-
version: '0.2.2-dev',
75-
timestamp: new Date().toISOString()
76-
}));
77-
return;
78-
}
13+
FROM oven/bun:latest
7914

80-
if (req.method === 'GET' && req.url === '/status') {
81-
const config = readConfig();
82-
res.writeHead(200);
83-
res.end(JSON.stringify({
84-
state: 'running',
85-
port: PORT,
86-
config: config
87-
}));
88-
return;
89-
}
15+
# Install system dependencies: fnm prerequisites, sqlite, cron, nproc (via coreutils)
16+
RUN apt-get update && \
17+
apt-get install -y --no-install-recommends \
18+
curl \
19+
unzip \
20+
sqlite3 \
21+
cron \
22+
coreutils \
23+
tini \
24+
&& rm -rf /var/lib/apt/lists/*
9025

91-
if (req.method === 'GET' && req.url === '/api/config') {
92-
const config = readConfig();
93-
res.writeHead(200);
94-
res.end(JSON.stringify(config));
95-
return;
96-
}
26+
# Install fnm (Fast Node Manager)
27+
ENV FNM_DIR=/root/.fnm
28+
RUN curl -fsSL https://fnm.vercel.app/install | bash
9729

98-
if (req.method === 'POST' && req.url === '/api/config') {
99-
let body = '';
100-
req.on('data', chunk => body += chunk);
101-
req.on('end', () => {
102-
try {
103-
const cfg = JSON.parse(body);
104-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
105-
res.writeHead(200);
106-
res.end(JSON.stringify({ ok: true }));
107-
} catch (e) {
108-
res.writeHead(400);
109-
res.end(JSON.stringify({ error: e.message }));
110-
}
111-
});
112-
return;
113-
}
30+
# Install and activate Node.js 24 via fnm
31+
ENV PATH="/root/.fnm:/root/.fnm/aliases/default/bin:$PATH"
32+
RUN /bin/bash -c 'source /root/.fnm/fnm.sh && fnm install 24 && fnm default 24'
11433

115-
// Default: simple status page
116-
res.writeHead(200);
117-
res.end(JSON.stringify({
118-
service: 'openclaw-gateway',
119-
status: 'running',
120-
port: PORT,
121-
endpoints: ['/health', '/status', '/api/config']
122-
}));
123-
});
34+
# Ensure fnm is activated for all subsequent RUN commands and the final CMD
35+
ENV FNM_NODE_VERSION=24
36+
RUN /bin/bash -c 'source /root/.fnm/fnm.sh && fnm use 24 && node -v && npm -v'
12437

125-
ensureConfig();
126-
server.listen(PORT, '0.0.0.0', () => {
127-
console.log(`OpenClaw Gateway (dev) listening on port ${PORT}`);
128-
console.log(` Health: http://localhost:${PORT}/health`);
129-
console.log(` Config: http://localhost:${PORT}/api/config`);
130-
});
131-
GATEWAY_EOF
38+
# Create data directory
39+
RUN mkdir -p /root/.openclaw
13240

133-
# Set ownership
134-
RUN chown -R openclaw:openclaw /home/openclaw
41+
# Install OpenClaw globally via npm
42+
RUN /bin/bash -c 'source /root/.fnm/fnm.sh && fnm use 24 && npm install -g openclaw'
13543

13644
# Expose gateway port
13745
EXPOSE 18789
@@ -143,6 +51,5 @@ HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=5 \
14351
# Use tini as init system for proper signal handling
14452
ENTRYPOINT ["tini", "--"]
14553

146-
# Default command: run the gateway in foreground
147-
USER openclaw
148-
CMD ["node", "gateway.js"]
54+
# Activate fnm + Node 24 and start the OpenClaw gateway
55+
CMD ["/bin/bash", "-c", "source /root/.fnm/fnm.sh && fnm use 24 && openclaw gateway run"]

0 commit comments

Comments
 (0)