kyle-ai commited on
Commit
b4ee1ca
·
verified ·
1 Parent(s): 99f40b4

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +100 -32
Dockerfile CHANGED
@@ -65,69 +65,137 @@ if __name__ == "__main__":\n\
65
  if len(sys.argv) > 1 and sys.argv[1] == "backup": backup()\n\
66
  else: restore()' > /usr/local/bin/sync.py
67
 
68
- # 6. 最终启动脚本 (增加进程清理与锁文件强制删除)
69
  RUN echo "#!/bin/bash\n\
70
  mkdir -p /root/.openclaw\n\
71
  ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\
72
  \n\
73
- # 1. 尝试从云端恢复配置\n\
74
- python3 /usr/local/bin/sync.py restore\n\
75
  find /root/.openclaw -name \"*.lock\" -delete\n\
76
  chmod 700 /root/.openclaw\n\
77
  \n\
78
- # 2. 判断配置文件是否存在,如果不存在(首次运行或恢复失败)才使用环境变量生成\n\
79
- if [ ! -f /root/.openclaw/openclaw.json ]; then\n\
80
- echo \"--- [System] 📝 未检测到配置文件,正在使用环境变量初始化... ---\"\n\
81
- CLEAN_BASE=\$(echo \"\$OPENAI_API_BASE\" | sed \"s|/chat/completions||g\" | sed \"s|/v1/|/v1|g\")\n\
82
- cat > /root/.openclaw/openclaw.json <<EOF\n\
83
- {\n\
84
- \"models\": { \"providers\": { \"siliconflow\": { \"baseUrl\": \"\$CLEAN_BASE\", \"apiKey\": \"\$OPENAI_API_KEY\", \"api\": \"openai-completions\", \"authHeader\": true, \"models\": [{ \"id\": \"\$MODEL\", \"name\": \"DeepSeek\", \"contextWindow\": 128000 }] } } },\n\
85
- \"agents\": { \"defaults\": { \"model\": { \"primary\": \"siliconflow/\$MODEL\" } } },\n\
86
- \"gateway\": {\n\
87
- \"mode\": \"local\", \"port\": 7860, \"bind\": \"custom\", \"customBindHost\": \"0.0.0.0\",\n\
88
- \"trustedProxies\": [\"10.0.0.0/8\"],\n\
89
- \"auth\": { \"mode\": \"token\", \"token\": \"\$OPENCLAW_GATEWAY_PASSWORD\" },\n\
90
- \"controlUi\": { \"enabled\": true, \"allowInsecureAuth\": true, \"dangerouslyDisableDeviceAuth\": true, \"dangerouslyAllowHostHeaderOriginFallback\": true },\n\
91
- \"tools\": { \"deny\": [\"gateway\"] }\n\
92
- }\n\
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  }\n\
94
- EOF\n\
95
- else\n\
96
- echo \"--- [System] 📂 检测到已有配置文件,跳过初始化。 ---\"\n\
97
- fi\n\
98
  \n\
99
- # 3. 启动后台备份任务\n\
 
 
 
 
 
 
 
100
  (while true; do sleep 1800; python3 /usr/local/bin/sync.py backup; done) &\n\
101
  \n\
102
  export NODE_ENV=production\n\
103
  export OPENCLAW_TRUST_PROXY=true\n\
104
  \n\
105
- # 4. 守护进程模式运行 openclaw\n\
106
  set +e\n\
107
  trap 'kill -TERM \$PID 2>/dev/null' TERM INT\n\
108
  \n\
109
  while true; do\n\
110
- echo \"--- [System] 🚀 正在启动/重启 OpenClaw Gateway... ---\"\n\
111
- \n\
112
- # 每次启动前,确保没有任何旧进程和锁文件残留\n\
113
  find /root/.openclaw -name \"*.lock\" -delete\n\
114
  \n\
115
  openclaw gateway run --port 7860 &\n\
116
  PID=\$!\n\
117
  wait \$PID\n\
118
  \n\
119
- echo \"--- [System] ⚠️ OpenClaw 主进程退出,正在进行清理与内部重启... ---\"\n\
120
- \n\
121
- # 关键修复:执行官方的停止命令,并强杀可能残留的 node 幽灵进程\n\
122
  openclaw gateway stop || true\n\
123
  pkill -f openclaw || true\n\
124
  pkill -f node || true\n\
125
  \n\
126
- # 强制进行一次备份\n\
127
  python3 /usr/local/bin/sync.py backup || true\n\
128
- \n\
129
  sleep 3\n\
130
  done\n\
131
  " > /usr/local/bin/start-openclaw && chmod +x /usr/local/bin/start-openclaw
 
132
  EXPOSE 7860
133
  CMD ["/usr/local/bin/start-openclaw"]
 
65
  if len(sys.argv) > 1 and sys.argv[1] == "backup": backup()\n\
66
  else: restore()' > /usr/local/bin/sync.py
67
 
68
+ # 6. 最终启动脚本 (优化配置合并策略:严格深度合并 + 数组按ID智能合并)
69
  RUN echo "#!/bin/bash\n\
70
  mkdir -p /root/.openclaw\n\
71
  ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\
72
  \n\
73
+ echo \"--- [System] 📦 1. 尝试从云端恢复配置... ---\"\n\
74
+ python3 /usr/local/bin/sync.py restore || true\n\
75
  find /root/.openclaw -name \"*.lock\" -delete\n\
76
  chmod 700 /root/.openclaw\n\
77
  \n\
78
+ echo \"--- [System] 📝 2. 开始合并默认配置与已恢复的配置... ---\"\n\
79
+ export CLEAN_BASE=\$(echo \"\$OPENAI_API_BASE\" | sed \"s|/chat/completions||g\" | sed \"s|/v1/|/v1|g\")\n\
80
+ \n\
81
+ # 使用 Python 深度合并 JSON (包含数组按ID合并逻辑)\n\
82
+ python3 -c \"\n\
83
+ import json, os\n\
84
+ \n\
85
+ def deep_update(d, u):\n\
86
+ for k, v in u.items():\n\
87
+ if isinstance(v, dict) and k in d and isinstance(d[k], dict):\n\
88
+ deep_update(d[k], v)\n\
89
+ elif isinstance(v, list) and k in d and isinstance(d[k], list):\n\
90
+ # 处理数组合并逻辑\n\
91
+ d_dict = {}\n\
92
+ non_id_d = []\n\
93
+ # 解析原配置(恢复的)数组\n\
94
+ for item in d[k]:\n\
95
+ if isinstance(item, dict) and 'id' in item:\n\
96
+ d_dict[item['id']] = item\n\
97
+ else:\n\
98
+ non_id_d.append(item)\n\
99
+ \n\
100
+ non_id_u = []\n\
101
+ # 解析新配置(环境变量)数组并进行合并\n\
102
+ for item in v:\n\
103
+ if isinstance(item, dict) and 'id' in item:\n\
104
+ if item['id'] in d_dict:\n\
105
+ # id相同,对内部字段继续深度合并(以新配置为准覆盖)\n\
106
+ d_dict[item['id']] = deep_update(d_dict[item['id']], item)\n\
107
+ else:\n\
108
+ d_dict[item['id']] = item\n\
109
+ else:\n\
110
+ # 对于普通元素(如字符串IP),去重合并\n\
111
+ if item not in non_id_d:\n\
112
+ non_id_u.append(item)\n\
113
+ \n\
114
+ # 组合合并后的数组\n\
115
+ d[k] = list(d_dict.values()) + non_id_d + non_id_u\n\
116
+ else:\n\
117
+ d[k] = v\n\
118
+ return d\n\
119
+ \n\
120
+ config_path = '/root/.openclaw/openclaw.json'\n\
121
+ current_config = {}\n\
122
+ \n\
123
+ if os.path.exists(config_path):\n\
124
+ try:\n\
125
+ with open(config_path, 'r', encoding='utf-8') as f:\n\
126
+ current_config = json.load(f)\n\
127
+ except Exception:\n\
128
+ pass\n\
129
+ \n\
130
+ clean_base = os.environ.get('CLEAN_BASE', '')\n\
131
+ api_key = os.environ.get('OPENAI_API_KEY', '')\n\
132
+ model = os.environ.get('MODEL', '')\n\
133
+ gateway_pw = os.environ.get('OPENCLAW_GATEWAY_PASSWORD', '')\n\
134
+ \n\
135
+ default_config = {\n\
136
+ 'models': {\n\
137
+ 'providers': {\n\
138
+ 'siliconflow': {\n\
139
+ 'baseUrl': clean_base,\n\
140
+ 'apiKey': api_key,\n\
141
+ 'api': 'openai-completions',\n\
142
+ 'authHeader': True,\n\
143
+ 'models': [{'id': model, 'name': 'DeepSeek', 'contextWindow': 128000}]\n\
144
+ }\n\
145
+ }\n\
146
+ },\n\
147
+ 'agents': {\n\
148
+ 'defaults': {\n\
149
+ 'model': {'primary': 'siliconflow/' + model}\n\
150
+ }\n\
151
+ },\n\
152
+ 'gateway': {\n\
153
+ 'mode': 'local', 'port': 7860, 'bind': 'custom', 'customBindHost': '0.0.0.0',\n\
154
+ 'trustedProxies': ['10.0.0.0/8'],\n\
155
+ 'auth': {'mode': 'token', 'token': gateway_pw},\n\
156
+ 'controlUi': {\n\
157
+ 'enabled': True,\n\
158
+ 'allowInsecureAuth': True,\n\
159
+ 'dangerouslyDisableDeviceAuth': True,\n\
160
+ 'dangerouslyAllowHostHeaderOriginFallback': True\n\
161
+ },\n\
162
+ 'tools': {'deny': ['gateway']}\n\
163
+ }\n\
164
  }\n\
 
 
 
 
165
  \n\
166
+ merged_config = deep_update(current_config, default_config)\n\
167
+ \n\
168
+ with open(config_path, 'w', encoding='utf-8') as f:\n\
169
+ json.dump(merged_config, f, indent=2, ensure_ascii=False)\n\
170
+ \"\n\
171
+ echo \"--- [System] ✅ 配置合并完成。 ---\"\n\
172
+ \n\
173
+ # 启动后台备份任务\n\
174
  (while true; do sleep 1800; python3 /usr/local/bin/sync.py backup; done) &\n\
175
  \n\
176
  export NODE_ENV=production\n\
177
  export OPENCLAW_TRUST_PROXY=true\n\
178
  \n\
179
+ echo \"--- [System] 🚀 3. 正在启动 OpenClaw Gateway... ---\"\n\
180
  set +e\n\
181
  trap 'kill -TERM \$PID 2>/dev/null' TERM INT\n\
182
  \n\
183
  while true; do\n\
 
 
 
184
  find /root/.openclaw -name \"*.lock\" -delete\n\
185
  \n\
186
  openclaw gateway run --port 7860 &\n\
187
  PID=\$!\n\
188
  wait \$PID\n\
189
  \n\
190
+ echo \"--- [System] ⚠️ OpenClaw 主进程退出,正在清理环境准备重启... ---\"\n\
 
 
191
  openclaw gateway stop || true\n\
192
  pkill -f openclaw || true\n\
193
  pkill -f node || true\n\
194
  \n\
 
195
  python3 /usr/local/bin/sync.py backup || true\n\
 
196
  sleep 3\n\
197
  done\n\
198
  " > /usr/local/bin/start-openclaw && chmod +x /usr/local/bin/start-openclaw
199
+
200
  EXPOSE 7860
201
  CMD ["/usr/local/bin/start-openclaw"]