1. 是什么（What）—— 直击本质Arrays.asList() 的本质陷阱：它期望的是泛型可变参数 T...，而基本类型数组 int[] 会被当成单个对象元素，导致 List<int[]> 而非 List<Integer>。类比：你本人校招面试，HR说"带简历来"，结果你拿了一个"文件夹"（数组整体）而不是"一张张简历"（数组展开）。直接上代码 List<Integer> list = Arrays.asList(new int[]{1,2,3,5,2}); // 会报错，因为Arrays.asList将`int[]`识别为单个对象，所以泛型不应该是`Integer`，而是`int[]`。 // 当然也可以直接写成 List<Integer> list = Arrays.asList(new Integer[]{1,2,3,5,2}); // 但这样便掉入了另一个陷阱，`Arrays.asList()` 返回的List不能增删！这个在进阶拓展里有详细说明 2. 怎么做（How）—— 代码与场景落地复现// ❌ 编译报错：不兼容的类型，无法将 int[] 转为 Integer[] List<Integer> list = Arrays.asList(new int[]{1, 2, 3, 5, 2}); // 错误信息（Java 8+）： // 错误: 无法将引用 List<int[]> 转换为 List<Integer> // List<Integer> list = Arrays.asList(new int[]{1,2,3,5,2}); // ^ // 需要: List<Integer> // 找到: List<int[]>四种正确转换方式（从面试到生产）int[] arr = {1, 2, 3, 5, 2}; // ========== 方案1：手动装箱（最原始，面试应急）========== List<Integer> list1 = new ArrayList<>(); for (int val : arr) { list1.add(val); // 自动装箱 int → Integer } // ========== 方案2：Stream（Java 8+，代码简洁，性能一般）========== List<Integer> list2 = Arrays.stream(arr) // IntStream .boxed() // Stream<Integer> .collect(Collectors.toList()); // 可变List // 不可变版本（更高效，内存友好） List<Integer> list2Immutable = Arrays.stream(arr) .boxed() .toList(); // Java 16+，返回ImmutableList // ========== 方案3：Apache Commons Lang（项目依赖可用）========== // List<Integer> list3 = org.apache.commons.lang3.ArrayUtils.toObject(arr); // ========== 方案4：Guava（Google出品，推荐）========== // List<Integer> list4 = com.google.common.primitives.Ints.asList(arr); // 返回的是 ImmutableList<Integer>，底层用 int[] 存储，省空间！ // ⚠️ 注意：Ints.asList() 返回的List不支持add/remove，set可行对比表：哪种场景用什么场景推荐方案原因算法题/面试手写方案1（手动）或方案2（Stream）无依赖，最安全大数据量（>10^6）方案4 Guava Ints.asList()避免 boxing 对象爆炸，内存省4倍频繁修改元素方案2 Collectors.toList()返回 ArrayList，支持set只读遍历方案2 .toList() Java 16+Immutable，线程安全提示3. 为什么（Why）—— 源码与底层原理3.1 为什么 int[] 会被当成单个元素？// JDK源码：Arrays.asList 的签名 public static <T> List<T> asList(T... a) { return new ArrayList<>(a); // 内部类 java.util.Arrays.ArrayList } // 泛型的本质：编译期擦除，运行时没有 T 的区别 // T... 在运行时实际上是 Object[]关键洞察：泛型 T 的上限是 Object，而 int[] 是对象（数组是Object的子类），所以：// 编译器看到的等价代码： T = int[] → 因为 int[] extends Object，满足 T 的约束 T... a → int[][] 的退化，实际传入 new int[][]{ new int[]{1,2,3} }3.2 对比 Integer[] vs int[] 的深层差异Integer[] boxedArr = {1, 2, 3}; // ✅ 可以，T = Integer int[] primitiveArr = {1, 2, 3}; // ❌ T 推断为 int[] // 验证：拆箱看看泛型擦除后的真相 List<?> list = Arrays.asList(primitiveArr); System.out.println(list.get(0).getClass()); // class [I → int[] 的类型签名！ System.out.println(list.size()); // 1，不是4！JVM 类型签名秘密：类型签名含义int[][I[数组 + IntInteger[][Ljava/lang/Integer;[数组 + L引用类型int[][][[I二维数组3.3 自动拆装箱的性能代价// 看似等价，性能差10倍 for (Integer val : list) { ... } // 频繁拆箱：Integer.intValue() for (int val : intArray) { ... } // 原生操作，CPU缓存友好 // 内存对比（64位JVM，压缩指针） int[1000] → 约 4KB （原始数据） Integer[1000] → 约 16KB 对象头 + 4KB引用 + 16KB Integer对象 = 36KB+4. 【进阶拓展】面试致命陷阱与调优4.1 更隐蔽的陷阱：Arrays.asList() 返回的List不能增删！Integer[] boxedArr = { 1, 2, 3 }; List<Integer> list = Arrays.asList(boxedArr); list.add(4); // ❌ UnsupportedOperationException！ // 源码真相：返回的是 Arrays$ArrayList，不是 java.util.ArrayList // 它继承 AbstractList，但只实现了 set/get/size，add/remove抛异常 boxedArr[0]=5; System.out.println(list.getFirst());// 5，原数组修改会影响list，说明二者共用一个指针 // 正确处理：必须包一层，这样就是一个全新的对象了，继承全部方法同时不受原数组修改的影响 List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3));4.2 算法题高性能方案：避免 Stream 开销// ❌ 慢：Stream 有函数对象、状态机开销 List<Integer> slow = Arrays.stream(arr).boxed().collect(Collectors.toList()); // ✅ 快：预分配 + 手动循环，算法题首选（尤其10^5以上数据） int[] arr = {1, 2, 3, 5, 2}; List<Integer> fast = new ArrayList<>(arr.length); for (int v : arr) fast.add(v); // ✅ 更快：如果只需要遍历，不转List，直接用 int[] // 或转基本类型，用 Trove/FastUtil/Eclipse Collections4.3 让面试官眼前一亮的回答"这里有个细节：Arrays.asList 对基本类型数组有陷阱。int[] 会被当成 T 的单个元素，因为泛型 T... 的擦除上限是 Object，而数组是对象。我更喜欢用 IntStream 显式 boxing，或者大数据量时用 Guava 的 Ints.asList，它底层保留 int[] 避免对象爆炸。"4.4 一张图彻底理解调用: Arrays.asList(new int[]{1,2,3}) │ ▼ T... a where T = int[] ← 泛型推断 │ ▼ new List<int[]> 包含一个元素: {int[]{1,2,3}} │ ▼ ❌ 无法赋值给 List<Integer> 对比: 调用: Arrays.asList(new Integer[]{1,2,3}) │ ▼ T... a where T = Integer ← 正确推断 │ ▼ List<Integer> 包含三个元素: {1,2,3} │ ▼ ✓ 正确终极对照表：快速解决需求代码注意点int[] → List<Integer>Arrays.stream(arr).boxed().toList()Java 16+ 用 .toList()int[] → List<Integer> (旧版)...boxed().collect(Collectors.toList())可变ListInteger[] → List<Integer>Arrays.asList(integerArr)部分方法缺失，原始数组修改会影响List避免所有装箱用 IntStream，或直接操作 int[]算法题首选极致内存省空间Guava Ints.asList() / Eclipse IntList返回视图，非真正List
是什么？有道经典算法题：给你一个文本串 T ，一个非空模板串 S ，问 S 在 T 中出现了多少次 数据范围：1≤𝑙𝑒𝑛(𝑆)≤500000,1≤𝑙𝑒𝑛(𝑇)≤1000000 要求：空间复杂度 𝑂(𝑙𝑒𝑛(𝑆))，时间复杂度 𝑂(𝑙𝑒𝑛(𝑆)+𝑙𝑒𝑛(𝑇))我第一次写的答案import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可 * * 计算模板串S在文本串T中出现了多少次 * @param S string字符串 模板串 * @param T string字符串 文本串 * @return int整型 */ public int kmp (String S, String T) { int n = 0; int l = (T.length() - S.length()) + 1; for (int i = 0; i < l; i++) { if (T.startsWith(S,i)) { n++; } } return n; } }运行发现时间复杂度太大，速度超过了2s。这是标准答案public int kmp(String S, String T) { if (S.length() > T.length()) return 0; // ========== 第一步：预处理模式串 ========== int[] next = new int[S.length()]; // i: 当前字符位置，j: 已匹配的前缀长度（也是下一个要比的位置） for (int i = 1, j = 0; i < S.length(); i++) { while (j > 0 && S.charAt(i) != S.charAt(j)) { j = next[j - 1]; // 失配：回退到次优候选 } if (S.charAt(i) == S.charAt(j)) { j++; // 匹配：扩展前缀 } next[i] = j; // 记录：S[0..i]的最长公共前后缀长度 } // ========== 第二步：KMP匹配 ========== int count = 0; for (int i = 0, j = 0; i < T.length(); i++) { while (j > 0 && T.charAt(i) != S.charAt(j)) { j = next[j - 1]; // 失配：S滑动，T不动 } if (T.charAt(i) == S.charAt(j)) { j++; // 匹配：双双前进 } if (j == S.length()) { count++; j = next[j - 1]; // 成功：保留重叠，继续搜索 } } return count; }[scode type="yellow"]光知道代码没用，得理解才行，为什么要这样写。[/scode]怎么做理解next数组的物理意义next[i] = 模式串S[0..i]中，最长相等"真前缀"与"真后缀"的长度术语定义例子（S="ababab"）真前缀不包含自身的所有前缀"a", "ab", "aba", "abab", "ababa"真后缀不包含自身的所有后缀"b", "ab", "bab", "abab", "babab"最长相等对同一个字符串既是前缀又是后缀"abab"（长度4）理解next数组的“递推”核心思想：已知next[i-1]，如何求next[i]？模式串: a b a b a b c 索引: 0 1 2 3 4 5 6 已知: next[4] = 3 （"ababa"的最长公共前后缀是"aba"） 求: next[5] = ? （"ababab"的最长公共前后缀）其实这里我还是没理解递推的含义，所以有了下面这个图：S[0..4] = "ababa" 想扩展成 S[0..5] = "ababab" ↑ ↑ 前缀"aba" (长度3) 期望: 前缀"abab" (长度4) 后缀"aba" (长度3) 期望: 后缀"abab" (长度4) 关键观察：如果 S[3] == S[5]，就能直接扩展！ （"aba"的下一个字符） （新字符） 即：如果 S[next[4]] == S[5]，则 next[5] = next[4] + 1 = 4这里我终于懂了，如果当前已知的最大公共前后缀的下一位和最后一位相等，那么就产生了一个新的更长的公共前后缀。失配时的“回退”如果不相等怎么办？S = "abacabad" 求 next[6]，已知 next[5]=3（"abacab"的"abab"? 不对，重新算...） 让我重新来：S="abacabad" 索引: 0 1 2 3 4 5 6 7 字符: a b a c a b a d next[0] = 0 （"a"，无真前后缀） next[1] = 0 （"ab"，无相等前后缀） next[2] = 1 （"aba"，"a"="a"） next[3] = 0 （"abac"，无） next[4] = 1 （"abaca"，"a"="a"） next[5] = 2 （"abacab"，"ab"="ab"） next[6] = 3? （"abacaba"，期望"aba"="aba" → 是！） 现在求 next[7]：S[7]='d'，S[3]='c'，不相等！怎么回退：当前: "abacaba" + 'd' ↑ 已匹配前缀长度3（"aba"） "aba" + 'd' 期望匹配 "aba" + 'c'? 不对... 回退到 next[2]=1，即前缀"a" "a" + 'd' 期望匹配 "a" + 'b'? 不对... 再回退到 next[0]=0 "" + 'd'，从头开始，next[7]=0到这里大概明白next数组怎么来的了。 // ========== 步骤1: 构建next数组 ========== int[] next = new int[sLen]; // next[i] = S[0..i]的最长相等真前缀与真后缀的长度 // 手动设置next[0] = 0（单个字符无真前后缀） for (int i = 1, j = 0; i < sLen; i++) { // j: 当前已匹配的最长前缀长度，也是下一个要比较的位置 // 失配：回退j到前一个可能的匹配位置 while (j > 0 && S.charAt(i) != S.charAt(j)) { j = next[j - 1]; } // 匹配成功：扩展匹配长度 if (S.charAt(i) == S.charAt(j)) { j++; } next[i] = j; }在执行MKP匹配的时候类似于next的形成，只不过在j=S.length时回退到S的上一个最大公共子串。记住了next数组的算法KMP的算法也就自然带出了。为什么问题自测为什么next[0]=0？单个字符没有真前后缀为什么匹配成功后j=next[j-1]？保留最长可复用前缀，允许重叠匹配为什么失配时j=next[j-1]而不是next[j]？next[j]是S[0..j]的，我们要的是S[0..j-1]的时间复杂度为什么是O(n)？i只进不退，每个字符最多被比较2次（前进+回退），回退总量≤前进总量
问题现象frunoob.cn 配置了 IP 白名单，但任何 IP 都能访问，限制完全没生效。原因分析Nginx 处理请求分多个阶段：rewrite → access → content → ...allow/deny 在 access 阶段执行return 在 rewrite 阶段执行rewrite 阶段先于 access 阶段！所以 return 200 直接返回响应，allow/deny 根本没机会执行。对比验证ai.frunoob.cn（生效）使用 proxy_pass，无 return，正常走 access 阶段。frunoob.cn（不生效）使用 return 200，rewrite 阶段直接返回，跳过 access。解决方案去掉 return，改用 root + index 或 proxy_pass。关键结论指令执行阶段影响 allow/denyreturnrewrite会跳过rewriterewrite会跳过proxy_passcontent不会跳过root/indexcontent不会跳过使用 return 或 rewrite 时，allow/deny 会失效！
[scode type="yellow"]以下方法只能保证不会更新，并不提示更新消息，但不保证点击右上角不闪退[/scode][scode type="red"]我发现闪退往往出现在第二次点击右上角【Customise and control Google Chrome】[/scode]是什么因为最新版本限制第三方抓取cookie，所以必须保持在旧版本，但是就算停止了服务，每次打开右上角都会出现finish update，导致无法进入到设置，一点右上角三个点就自动关闭，就很烦。怎么做步骤 1：禁用更新服务按 Win + R，输入 services.msc，回车找到 Google Update Service (gupdate) 和 Google Update Service (gupdatem)分别双击，将启动类型改为 禁用，然后点击 停止，确定[scode type="yellow"]我直接把所有带Google的都禁用了，计划任务也删了[/scode]步骤2：修改快捷方式启动参数这种方法只关闭右上角的更新提示，不会阻止 Chrome 自动更新，但仅在你通过修改后的快捷方式启动时生效。在桌面找到 Google Chrome 图标，右键 → 属性切换到 快捷方式 标签页在 目标 一栏的末尾（引号外面）加一个空格，然后粘贴：--disable-background-networking点击 确定 保存重启 Chrome 即可[scode type="blue"]注意：如果 Chrome 固定在任务栏，需要先从任务栏取消固定，修改桌面快捷方式后，重新固定到任务栏。[/scode]步骤三 锁死更新文件更新文件在C:\Program Files (x86)\Google下。网上也有说在这两个地方的，但我找不到，最后我是在资源管理器中直接搜到的GoogleUpdate.exe。C:\Program Files (x86)\Google\Update\ C:\Users\你的用户名\AppData\Local\Google\Update\为什么为什么不修改注册表，更彻底，对所有启动方式有效一般情况不动注册表，修改错了容易让系统出错，以前就因为清理系统垃圾的时候过度修改过注册表，结果系统出问题了，重装系统后才好，所以不懂得注册表不要按网上随便改。为啥没有 锁死更新文件夹不知道为啥我的Chrome没有Update文件夹，我没有实操过所以没写。以下是网上得步骤：打开文件夹：C:\Program Files (x86)\Google\Update 删除该文件夹内的所有内容 右键 Update 文件夹 → 属性 → 安全 选项卡 点击 编辑，找到 SYSTEM，将它的权限全部设为 拒绝 点击确定保存
install国内安装每次更新前，先在终端运行 claude 的情况下退出 Claude Code，再执行 npm update -g @anthropic-ai/claude-code，npm 就能顺利清理临时目录了。npm config set registry https://registry.npmmirror.com npm install -g @anthropic-ai/claude-code # 切换回官方 npm config set registry https://registry.npmjs.org # 先执行一次claude命令，然后会自动生成配置文件，但是让你登陆后才能使用，此时就可以退出了 接下来修改配置文件即可 (linux)~/.claude/settings.json (windows) C:\Users\<User>\.claude\settings.jsondeepseek{ "env": { "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic", "ANTHROPIC_AUTH_TOKEN": "sk-", "ANTHROPIC_MODEL": "deepseek-v4-flash", "ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4-pro", "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek-v4-pro", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek-v4-flash", "CLAUDE_CODE_SUBAGENT_MODEL": "deepseek-v4-flash", "CLAUDE_CODE_EFFORT_LEVEL": "max" }, "model": "deepseek-v4-flash", "enabledPlugins": { "code-simplifier@claude-plugins-official": true }, "theme": "dark" }moonshot{ "env": { "ANTHROPIC_BASE_URL": "https://api.moonshot.cn/anthropic", "ANTHROPIC_AUTH_TOKEN": "sk-", "ANTHROPIC_MODEL": "kimi-k2.5", "ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k2.6", "ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k2.6", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2.5", "CLAUDE_CODE_SUBAGENT_MODEL": "kimi-k2.5", "CLAUDE_CODE_EFFORT_LEVEL": "max", "ENABLE_TOOL_SEARCH": "false" }, "model": "haiku", "enabledPlugins": { "code-simplifier@claude-plugins-official": true }, "theme": "dark" }[scode type="green"]建议搞一个claude code router,接入免费模型，目前我每天用免费api都够用了 modelscope最靠谱[/scode]
Android 应用分身|双开|隐私空间 下用户证书不生效
是什么简单来说，无论是应用双开、应用分身还是隐私空间，它们底层的实现原理大多是基于 Android 的 Multiple Users（多用户机制）。主应用运行在宿主用户（User 0）下，而分身应用运行在另一个独立的用户空间（比如 User 10 或 User 999）下。核心问题在于：Android 的“用户证书（User Credentials）”是按用户空间（User）隔离的。 你在手机设置里安装的证书，默认只写入了主用户（User 0），分身用户根本读不到，而且系统默认没有提供为分身用户安装证书的入口。如何做下载ADB[scode type="red"]如果遇到adb找不到设备的情况，请排查：USB调试开启了吗？MTP文件传输开启了吗？仅充电允许ADB开启了吗？ADB/MTP驱动正常吗（打开设备管理器 → 存在未知设备（感叹号））如果是驱动问题，安装华为驱动后可直接修复，点我访问下载主页[/scode]获取分身用户的 IDadb shell pm list users将证书安装到分身用户adb shell am start --user <用户ID> -a android.credentials.INSTALL adb shell pm clear --user <USER_ID> com.android.certinstaller效果： 手机屏幕上会弹出一个熟悉的安全界面，提示你选择并安装证书。此时安装的证书将专门服务于分身应用。为什么为什么不直接把用户证书提升为系统证书？需要root权限。为什么还要操作手机，不直接用命令完成证书安装？因为 Android 系统的凭据存储（KeyStore）不是一个简单的、暴露在用户层面的文件夹，而是一个受到系统底层硬件（如安全芯片/TEE）保护的加密数据库。每个用户空间（User）的加密密钥都是隔离的。为什么不使用Xposed JustTrustMe？JustTrustMe 是一个基于 Xposed 框架的开源模块。它的核心原理非常暴力且有效： 它通过 Hook（拦截）Android 系统中几乎所有主流的网络请求库（如 HttpClient、OkHttp、Volley、WebView 等），强行把里面的证书校验逻辑返回值改成“True”。如果是自己开发的app，在开发测试阶段当然可以使用该模块，但是当前需求是用户证书如何作用于【微信分身】上。写在最后[scode type="red"]实际测试的时候，发现在华为老版本系统上EMUI系统上，副用户安装证书后可用，但在HONOR 10上副用户安装证书但应用识别不到，应该是魔改系统，证书逻辑不一样。[/scode]
第一步使用官方脚本卸载wget https://download.bt.cn/install/bt-uninstall.sh bash bt-uninstall.sh清理模式选择2清理残留文件rm -rf /www[font color="OrangeRed"]这会将网站，证书，docker-compose配置，数据库等全部清理，请确保备份以免后续有需要的文件被意外删除了[/font]清理残留服务一共要清理两个残留服务site_total.service,spring_executor.servicesystemctl list-units --type=service # 禁用服务并不会清理service源文件，所以这里看看service源文件到底在哪里，在disable之后手动删除它！ systemctl status site\_total.service cat /etc/systemd/system/site\_total.service sudo systemctl stop site_total.service sudo systemctl disable site_total.servicesudo systemctl status spring_executor.service cat /usr/lib/systemd/system/spring_executor.service sudo systemctl stop spring_executor sudo systemctl disable spring_executor sudo systemctl daemon-reload sudo systemctl reset-failed[scode type="red"]随着宝塔面板的更新可能会出现别的服务，所以分享一个清理想法，宝塔面板的服务名称似乎都是用下划线连接单词的[/scode]
本内容聚焦Docker Compose实操应用，精简基础容器命令，主打多容器编排部署，汇总项目启停、配置编写、服务管理、环境调试等常用操作，适配日常项目快速搭建与运维场景。查看容器查看所有可用字段## 查看所有可用字段 docker ps --format "{{json .}}" { "Command": "\"/entrypoint.sh mysq…\"", "CreatedAt": "2026-02-01 21:47:18 +0800 CST", "HealthStatus": "healthy", "ID": "6591d25f9ae8", "Image": "mysql/mysql-server:5.7", "Labels": "com.docker.compose.config-hash=0d064f827a3e4a9d3bb3b2f01a6e80b32644cae8d996dfdb3d5a67f2c1ce843c,com.docker.compose.container-number=1,com.docker.compose.depends_on=,com.docker.compose.image=sha256:a4ad24fe52cdf82a35c6f2dae7670cfebf39357de983cb909db07c8b56df4dd1,com.docker.compose.oneoff=False,com.docker.compose.project.config_files=/www/server/panel/data/compose/app-compose/docker-compose.yaml,com.docker.compose.project.working_dir=/www/server/panel/data/compose/app-compose,com.docker.compose.project=app-compose,com.docker.compose.replace=mysql57,com.docker.compose.service=mysql57,com.docker.compose.version=2.39.1", "LocalVolumes": "1", "Mounts": "app-compose_my…", "Names": "mysql57", "Networks": "app-compose_default-network", "Platform": null, "Ports": "33060/tcp, 0.0.0.0:3307-\u003e3306/tcp, [::]:3307-\u003e3306/tcp", "RunningFor": "3 months ago", "Size": "88B (virtual 432MB)", "State": "running", "Status": "Up 9 hours (healthy)" }以表格形式（带标题）输出全部容器并指定字段docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}\t{{.Size}}\t{{.State}}" -a 4155921bc878 watchtower 0B (virtual 17.4MB) exited 4cec5eb6ccf4 mysql80 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060-33061/tcp 90B (virtual 496MB) running 6591d25f9ae8 mysql57 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp 88B (virtual 432MB) running配置默认格式，避免每次都要写# ~/.docker/config.json 中添加 { "psFormat":"table {{.ID}}\t{{.Names}}\t{{.Ports}}\t{{.Size}}\t{{.State}}" }ps的等价命令docker container ls -a CONTAINER ID NAMES PORTS SIZE STATE ff566067f269 interview-redis 0B (virtual 117MB) exited 0496f4af3dc7 interview-postgres 0B (virtual 438MB) exited 45feb05752c2 interview-rustfs 4.59kB (virtual 283MB) exited清理1.查看占用情况docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 27 20 118.6GB 30.01GB (25%) Containers 20 11 8.126GB 7.91GB (97%) Local Volumes 11 9 4.139GB 83.92kB (0%) Build Cache 195 0 16.43GB 16.43GB2.查看所有容器docker ps -a CONTAINER ID NAMES PORTS SIZE STATE ff566067f269 interview-redis 0B (virtual 117MB) exited 0496f4af3dc7 interview-postgres 0B (virtual 438MB) exited 45feb05752c2 interview-rustfs 4.59kB (virtual 283MB) exited 23bde4019011 litellm-litellm-1 18MB (virtual 1.91GB) exited 232c2fc8a015 litellm_db 0B (virtual 451MB) exited d21315add029 litellm-prometheus-1 0B (virtual 423MB) exited 746443e7e1e2 comfyui 0.0.0.0:8188->8188/tcp, [::]:8188->8188/tcp 70.9kB (virtual 24.8GB) running 042242fda663 trendradar-mcp 3333/tcp 25.4MB (virtual 379MB) running b5e42b4495ca open-webui 0.0.0.0:3000->8080/tcp, [::]:3000->8080/tcp 144MB (virtual 11.1GB) running 3ca0e6e24ca3 trendradar 0.0.0.0:8111->8080/tcp, [::]:8111->8080/tcp 23.8MB (virtual 395MB) running 25a072d4254c open-terminal 0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp 236kB (virtual 3.59GB) running 966353720f1a rsshub-rsshub-1 0.0.0.0:1200->1200/tcp, [::]:1200->1200/tcp 22MB (virtual 1.08GB) running 7f333b32c20f pdfmathtranslate-next 1.53GB (virtual 3.97GB) exited 4155921bc878 watchtower 0B (virtual 17.4MB) exited e3d3dd5db852 books2audio 6.36GB (virtual 41.9GB) exited ebb43b3e78ef rsshub-real-browser-1 0.0.0.0:3001->3000/tcp, [::]:3001->3000/tcp 0B (virtual 1.98GB) running 1f25c6d1ae9f rsshub-browserless-1 3000/tcp 11B (virtual 3.06GB) running b6590ba1232d rsshub-redis-1 6379/tcp 0B (virtual 94.7MB) running 4cec5eb6ccf4 mysql80 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060-33061/tcp 90B (virtual 496MB) running 6591d25f9ae8 mysql57 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp 88B (virtual 432MB) running3.查看所有卷docker volume ls DRIVER VOLUME NAME local app-compose_mysql57 local app-compose_mysql80 local docker_chatterbox-models local docker_chatterbox-voices local interview_postgres_data local interview_redis_data local interview_rustfs_data local litellm_postgres_data local litellm_prometheus_data local open-webui local rsshub_redis-data4.查看所有网络docker network ls \NETWORK ID NAME DRIVER SCOPE bebd1f2d39de app-compose_default-network bridge local 12c1fdcde363 baota_net bridge local 8ce21ad2033f book2audio-dev_default bridge local e3a084f959a2 bridge bridge local 5ac3bf6e2820 docker_default bridge local eb4ebd07320f host host local 338944cde06e interview_default bridge local 354a79465980 litellm_default bridge local 20a8f0d79d6c none null local aa94fe1ac046 rsshub_default bridge local 70f70089cc33 tools_default bridge local 2c0089785ed7 translate-tools_default bridge local5.查看当前上下文（连接的是哪里的docker）docker context ls NAME DESCRIPTION DOCKER ENDPOINT ERROR default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock desktop-linux Docker Desktop npipe:////./pipe/dockerDesktopLinuxEnginedefault后面带个 *说明这是当前正在使用的Docker引擎，也就是本地的。而第二个 desktop-linux是Docker Desktop 安装时会自动创建 desktop-linux 这个 context，用来连接它内置的 Linux 虚拟机。由于我现在完全使用WSL，所以决定删除 desktop-linux，但在这之前需要再次确认它已经失效：docker context use desktop-linux docker ps结果显示 Failed to initialize: protocol not available说明已经不可用了，可用放心删除了。docker context rm desktop-linux6.查看所有镜像docker image ls i Info → U In Use IMAGE ID DISK USAGE CONTENT SIZE EXTRA awwaawwa/pdfmathtranslate-next:latest 9462f7dfbc82 2.44GB 0B U books2audio:latest f8e880e0d490 35.5GB 0B U browserless/chrome:latest c6321df7e375 3.06GB 0B U containrrr/watchtower:latest e7dd50d07b86 14.7MB 0B7.删除容器删除已停止的容器 docker container prune强制删除单个容器 docker rm -f <ID/Name>删除所有容器（包括运行中） docker rm -f $(docker ps -aq)批量删除匹配名称的 docker ps -aqf "name=xxx" \| xargs docker rm -f# 删除interview、litellm、rsshub开头的几个CONTAINER docker ps -aqf "name=interview" | xargs docker rm -f docker ps -aqf "name=litellm" | xargs docker rm -f docker ps -aqf "name=rsshub" | xargs docker rm -f8.删除image删除悬空镜像（无标签） docker image prune删除所有未使用镜像 docker image prune -a强制删除单个镜像 docker rmi -f <IMAGE_ID>批量删除匹配仓库的 docker images -q "repo/*" \| xargs docker rmi9.删除卷场景命令⚠️ 风险删除未被挂载的卷docker volume prune数据会丢失删除指定卷docker volume rm <NAME>确认无容器使用查看卷占用空间docker system df -v仅查看，不删除10.删除网络场景命令删除未被使用的网络docker network prune删除手动创建的指定网络docker network rm <NAME>注意：默认的bridge/host/none 不会被删 启动我喜欢再docker-compose.yaml中配置好一切后一键启动。name: default networks: default-network: # 内部别名 external: true # 引用外部已有的网络 name: shared-network #全局可见的真实名称 volumes: open-webui: external: true # 该名称为全局的 不会添加项目前缀 name: open-webui # 显式写一眼就知道全局真实名称 mysql57: external: true name: mysql57 mysql80: external: true name: mysql80 services: open-webui: image: ghcr.io/open-webui/open-webui:cuda container_name: open-webui # 手动指定容器名称，全局唯一 restart: unless-stopped ports: - "3000:8080" extra_hosts: - "host.docker.internal:host-gateway" volumes: - open-webui:/app/backend/data deploy: resources: reservations: devices: - driver: nvidia count: all # 你只有一张卡，写 1 即可 capabilities: [gpu] networks: - default-network labels: - com.centurylinklabs.watchtower.enable=true # 标记该容器需要被 Watchtower 自动更新 mysql80: image: mysql/mysql-server:8.0 container_name: mysql80 # 手动指定容器名称，全局唯一 restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" ports: - "3306:3306" volumes: - mysql80:/var/lib/mysql networks: - default-network environment: MYSQL_ROOT_PASSWORD: root mysql57: image: mysql/mysql-server:5.7 container_name: mysql57 # 手动指定容器名称，全局唯一 restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" ports: - "3307:3306" volumes: - mysql57:/var/lib/mysql networks: - default-network environment: MYSQL_ROOT_PASSWORD: root comfyui: # 使用针对最新显卡优化的 cu124 镜像 image: yanwk/comfyui-boot:cu128-megapak-pt29 container_name: comfyui restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" networks: - default-network ports: - "8188:8188" environment: - HTTP_PROXY=http://${WINDOWS_HOST_IP}:10808 - HTTPS_PROXY=http://${WINDOWS_HOST_IP}:10808 - NO_PROXY=localhost,127.0.0.1,.local,host.docker.internal,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - TZ=Asia/Shanghai # 自动更新 ComfyUI 主程序 - AUTO_UPDATE=true # 针对 4060 Ti 的建议启动参数：开启监听，启用预览 - CLI_ARGS=--listen --preview-method auto --use-sage-attention --disable-xformers volumes: # 核心程序逻辑 - /mnt/g/AITools/comfy/comfy_docker:/root # 模型分流存储 - /mnt/g/AITools/comfy/ComfyUI_windows_portable/ComfyUI/models:/root/ComfyUI/models - /mnt/g/AITools/comfy/comfy_docker/ComfyUI/custom_nodes:/root/ComfyUI/custom_nodes - /mnt/c/Users/fqq13/.cache/huggingface/hub:/root/.cache/huggingface/hub - /mnt/c/Users/fqq13/.cache/torch/hub:/root/.cache/torch/hub # 用户数据与成果 - /mnt/g/AITools/comfy/ComfyUI_windows_portable/ComfyUI/input:/root/ComfyUI/input - /mnt/g/AITools/comfy/ComfyUI_windows_portable/ComfyUI/output:/root/ComfyUI/output - /mnt/g/AITools/comfy/ComfyUI_windows_portable/ComfyUI/user/default/workflows:/root/ComfyUI/user/default/workflows deploy: resources: reservations: devices: - driver: nvidia count: all # 你只有一张卡，写 1 即可 capabilities: [gpu] labels: - com.centurylinklabs.watchtower.enable=true # 标记该容器需要被 Watchtower 自动更新 trendradar: image: wantcat/trendradar:latest container_name: trendradar restart: unless-stopped networks: - default-network extra_hosts: - "host.docker.internal:host-gateway" ports: - "8111:8080" volumes: - /mnt/g/code/2TOOL/trendRadar/config:/app/config:ro - /mnt/g/code/2TOOL/trendRadar/output:/app/output environment: - HTTP_PROXY=http://${WINDOWS_HOST_IP}:10808 - HTTPS_PROXY=http://${WINDOWS_HOST_IP}:10808 - NO_PROXY=localhost,127.0.0.1,.local,host.docker.internal,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - TZ=Asia/Shanghai # Web 服务器 - ENABLE_WEBSERVER=${ENABLE_WEBSERVER:-false} - WEBSERVER_PORT=8080 - CRON_SCHEDULE=${CRON_SCHEDULE:-*/30 * * * *} - RUN_MODE=${RUN_MODE:-cron} - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true} labels: - com.centurylinklabs.watchtower.enable=true # 标记该容器需要被 Watchtower 自动更新 trendradar-mcp: image: wantcat/trendradar-mcp:latest container_name: trendradar-mcp restart: unless-stopped networks: - default-network extra_hosts: - "host.docker.internal:host-gateway" # ports: # - "3333:3333" volumes: - /mnt/g/code/2TOOL/trendRadar/config:/app/config:ro - /mnt/g/code/2TOOL/trendRadar/output:/app/output environment: - TZ=Asia/Shanghai - HTTP_PROXY=http://${WINDOWS_HOST_IP}:10808 - HTTPS_PROXY=http://${WINDOWS_HOST_IP}:10808 - NO_PROXY=localhost,127.0.0.1,.local,host.docker.internal,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 labels: - com.centurylinklabs.watchtower.enable=true # 标记该容器需要被 Watchtower 自动更新在docker-compose.yaml同目录下执行 docker compose up -d停止移除容器及其网络docker-compose down移除容器同时移除卷但这个命令不会删除配置了external: true的卷docker-compose down -v 这里有个问题，在WSL下直接down，但是Forwarded port来不及处理，/usr/bin/docker-proxy进程没有关闭导致docker认为相关network还在使用中所以不会清理。所以最好是先stop再down，如果已经出现了如上情况可以按照以下操作来清理无用的docker-proxy进程。# 先删除相关network docker network rm <NAME> # 杀死docker-proxy进程 sudo killall -9 docker-proxy # 重启docker sudo systemctl restart docker # 重新检查端口映射是否正确 不含无效映射 ps aux | grep docker-proxy 运维# 查看所有运行中的compose projects docker compose ls docker compose stop|restart|start # compose中每个容器的资源占用情况 docker compose stats # 查看compose日志，实时日志 docker compose logs --tail 1000 -f # 查看指定容器的日志 docker logs -f <ID/Name> # 查看容器的具体状态（卷，网络等） docker inspect <Name|ID> # 查看磁盘占用情况 docker system df 日常运维我更喜欢直接用vscode上的EXTENSIONS 名为：Container Tools，功能齐全，所有操作的命令会体现在TERMINAL中。CONTAINERS面板中可以直接查看容器的文件目录。docker compose则以文件夹的形式展示，一个文件夹下包含其所有服务，很难不爱。
Windows 远程桌面连接（RDP）要求的函数不受支持| CredSSP 加密 Oracle 修正
问题描述Windows 11 电脑进行了安全更新，要求强制使用高安全级别的凭据加密；而 Windows Server 2012 服务器可能很久没更新，或者没有启用对应的安全策略。当两边安全级别对不上时，Windows 11 为了保护你的安全，就会直接断开连接。解决措施reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters" /v AllowEncryptionOracle /t REG_DWORD /d 2 /f立即生效无需重启电脑。