{
    "version": "https://jsonfeed.org/version/1",
    "title": "新手爱记录",
    "home_page_url": "https://cooree.co/blog",
    "description": "新手爱记录 Blog",
    "items": [
        {
            "id": "https://cooree.co/blog/autodok-cicd-container-update",
            "content_html": "<p>容器更新工具里 watchtower 名气最大，但它的思路是<strong>轮询</strong>：每隔一段时间去问镜像仓库「有没有新镜像」。轮询间隔摆在那里，更新不够即时，还得给它开仓库的读权限。</p>\n<p>autodok 走的是另一条路：<strong>不轮询，只等通知</strong>。它暴露一个 HTTP API，CI 流水线构建完新镜像后 POST 一下，它就把镜像拉下来、用原配置重启容器。主动权在流水线手里，更新时机精确到「这次构建」。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"项目地址\">项目地址<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E9%A1%B9%E7%9B%AE%E5%9C%B0%E5%9D%80\" class=\"hash-link\" aria-label=\"项目地址的直接链接\" title=\"项目地址的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">GitHub：<a href=\"https://github.com/cars10/autodok\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">cars10/autodok</a>（Rust 编写，MIT 协议）</li>\n<li class=\"\">Docker Hub：<a href=\"https://hub.docker.com/r/cars10/autodok\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">cars10/autodok</a></li>\n</ul>\n<p>项目非常精简，只暴露两个端点：</p>\n<table><thead><tr><th>端点</th><th>鉴权</th><th>作用</th></tr></thead><tbody><tr><td><code>GET /health</code></td><td>不需要</td><td>健康检查，Docker daemon 可达时返回 200</td></tr><tr><td><code>POST /update</code></td><td>需要 API Key</td><td>拉取指定镜像并用原配置重启指定容器</td></tr></tbody></table>\n<p>推荐的工作流：</p>\n<ol>\n<li class=\"\">推送代码触发 CI</li>\n<li class=\"\">CI 构建并推送新镜像</li>\n<li class=\"\">CI 向 autodok 发 <code>POST /update</code>，带上容器名和新镜像 tag</li>\n<li class=\"\">autodok 拉镜像、按原配置（卷、环境变量等）重启容器</li>\n</ol>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"部署方式\">部署方式<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F\" class=\"hash-link\" aria-label=\"部署方式的直接链接\" title=\"部署方式的直接链接\" translate=\"no\">​</a></h2>\n<p>用 docker compose 起一个容器就行，官方仓库自带 <code>compose.yml</code>：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">services</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">autodok</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> cars10/autodok</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">container_name</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> autodok</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">restart</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> always</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\">#ports:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\">#  - 3000:3000</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">volumes</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> /var/run/docker.sock</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">/var/run/docker.sock</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> ./data</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">/data</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\">#- /home/user/.docker/config.json:/config.json</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>三个关键点：</p>\n<ul>\n<li class=\"\"><strong>挂载 <code>docker.sock</code></strong>：autodok 靠它操作本机容器，这是它能「重启别的容器」的前提</li>\n<li class=\"\"><strong><code>./data</code> 目录</strong>：API Key 持久化在这里，启动后从日志（<code>docker compose logs -f autodok</code>）或 <code>./data/api_key</code> 文件里都能拿到</li>\n<li class=\"\"><strong>端口默认注释掉了</strong>：推荐用 nginx / traefik 反代一个域名出来（比如 <code>autodok.example.com</code>），比直接暴露端口好管理，也方便流水线跨机访问</li>\n</ul>\n<p>如果从私有镜像仓库拉镜像，把最后一行 volume 的注释去掉，挂上你 <code>docker login</code> 过的 <code>config.json</code>，autodok 会复用里面的凭据。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"curl-手动触发\">curl 手动触发<a href=\"https://cooree.co/blog/autodok-cicd-container-update#curl-%E6%89%8B%E5%8A%A8%E8%A7%A6%E5%8F%91\" class=\"hash-link\" aria-label=\"curl 手动触发的直接链接\" title=\"curl 手动触发的直接链接\" translate=\"no\">​</a></h2>\n<p>最朴素的用法，排查问题或临时更新时很实用：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 健康检查（不需要鉴权）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-X</span><span class=\"token plain\"> GET </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"http://autodok.example.com/health\"</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 触发更新：把容器 myapp 更新到 myapp:1.2.0</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-X</span><span class=\"token plain\"> POST </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"http://autodok.example.com/update\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">     </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-H</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"Authorization: </span><span class=\"token string variable\" style=\"color:hsl(221, 87%, 60%)\">$API_KEY</span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">     </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-H</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"content-type: application/json\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">     </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-d</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">'{\"container\": \"myapp\", \"image\": \"registry.example.com/myapp:1.2.0\"}'</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 成功响应</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># {\"message\":\"Container 'myapp' restarted with new image 'registry.example.com/myapp:1.2.0'\"}</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><code>container</code> 必须是<strong>正在运行中</strong>的容器名；<code>image</code> 必须是仓库里已存在的镜像和 tag。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"与-gitlab-ci-结合\">与 GitLab CI 结合<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E4%B8%8E-gitlab-ci-%E7%BB%93%E5%90%88\" class=\"hash-link\" aria-label=\"与 GitLab CI 结合的直接链接\" title=\"与 GitLab CI 结合的直接链接\" translate=\"no\">​</a></h2>\n<p>在 <code>.gitlab-ci.yml</code> 里，构建推送镜像之后加一个 deploy 阶段：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">stages</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> build</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> deploy</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">build-image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">stage</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> build</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">script</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> docker build </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">t registry.example.com/myapp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">$CI_COMMIT_SHORT_SHA .</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> docker push registry.example.com/myapp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">$CI_COMMIT_SHORT_SHA</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">deploy</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">stage</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> deploy</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> curlimages/curl</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">latest</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">script</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">|</span><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\">      curl -X POST \"$AUTODOK_URL/update\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\">        -H \"Authorization: $AUTODOK_API_KEY\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\">        -H \"content-type: application/json\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\">        --max-time 300 \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token scalar string\" style=\"color:hsl(119, 34%, 47%)\">        -d \"{\\\"container\\\": \\\"myapp\\\", \\\"image\\\": \\\"registry.example.com/myapp:$CI_COMMIT_SHORT_SHA\\\"}\"</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">rules</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">if</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> $CI_COMMIT_BRANCH == \"main\"</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>两个变量在 GitLab 项目 <strong>Settings → CI/CD → Variables</strong> 里配置：<code>AUTODOK_URL</code>（autodok 的访问地址）和 <code>AUTODOK_API_KEY</code>（记得勾选 Masked）。deploy 阶段的 runner 用 <code>curlimages/curl</code> 镜像即可，不需要 docker。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"与-jenkins-结合\">与 Jenkins 结合<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E4%B8%8E-jenkins-%E7%BB%93%E5%90%88\" class=\"hash-link\" aria-label=\"与 Jenkins 结合的直接链接\" title=\"与 Jenkins 结合的直接链接\" translate=\"no\">​</a></h2>\n<p>Jenkinsfile 里同样在推送镜像后加一步：</p>\n<div class=\"language-groovy codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-groovy codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">stage('Deploy') {</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  steps {</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    sh '''</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      curl -X POST \"$AUTODOK_URL/update\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">        -H \"Authorization: $AUTODOK_API_KEY\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">        -H \"content-type: application/json\" \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">        --max-time 300 \\</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">        -d '{\"container\": \"myapp\", \"image\": \"registry.example.com/myapp:'\"$GIT_COMMIT_SHORT\"'\"}'</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    '''</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  }</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">}</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><code>AUTODOK_URL</code> 和 <code>AUTODOK_API_KEY</code> 放在 Jenkins 凭据里（Credentials Binding 注入为环境变量），<code>GIT_COMMIT_SHORT</code> 可以在前面 stage 里用 <code>git rev-parse --short HEAD</code> 提取。</p>\n<p>如果装了 HTTP Request 插件，也可以不用 curl，写成声明式：</p>\n<div class=\"language-groovy codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-groovy codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">stage('Deploy') {</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  steps {</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    httpRequest url: \"${env.AUTODOK_URL}/update\",</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">                httpMode: 'POST',</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">                contentType: 'APPLICATION_JSON',</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">                customHeaders: [[name: 'Authorization', value: env.AUTODOK_API_KEY]],</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">                requestBody: '{\"container\": \"myapp\", \"image\": \"registry.example.com/myapp:latest\"}',</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">                timeout: 300</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  }</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">}</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"实践中的几个坑\">实践中的几个坑<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E5%AE%9E%E8%B7%B5%E4%B8%AD%E7%9A%84%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"实践中的几个坑的直接链接\" title=\"实践中的几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>超时设置</strong>：<code>POST /update</code> 的耗时 = 拉镜像 + 重启容器。大镜像可能要几分钟，除了 curl 的 <code>--max-time</code>，前面反代（nginx 的 <code>proxy_read_timeout</code>）和 CI 客户端的超时也要同步放大，否则镜像还没拉完请求先断了——注意请求断了不影响 autodok 继续执行，只是你拿不到结果</li>\n<li class=\"\"><strong>一次只能更新一个容器</strong>：要更新多个容器就发多个请求，串行执行</li>\n<li class=\"\"><strong>API Key 保管</strong>：它等于这台机器容器层的操作权限，别写死在仓库里，一律走 CI 变量/凭据注入</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/autodok-cicd-container-update#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>autodok 的功能边界很清晰：不做镜像扫描、不做编排、不轮询，就老老实实提供「给我一个容器名和新镜像，我帮你原地更新」的 API。对「代码 push 后希望测试环境立刻更新」这类场景，比 watchtower 的轮询更精准，也比在流水线里直接 ssh 上去敲命令干净得多。项目很小，源码读完不用一顿饭的时间，值得上手一试。</p>",
            "url": "https://cooree.co/blog/autodok-cicd-container-update",
            "title": "autodok：让 CI 流水线按需更新容器的轻量工具",
            "summary": "autodok 提供一个 API，按需拉取新镜像并用原配置重启容器。记录它的部署方式，以及和 GitLab CI、Jenkins、curl 手动触发的几种用法。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "Docker",
                "CI/CD",
                "自动化运维",
                "autodok"
            ]
        },
        {
            "id": "https://cooree.co/blog/minio-mc-commands",
            "content_html": "<p>MinIO 本身部署很简单，但日常运维——传文件、同步目录、清旧数据、查容量——都要靠它的官方客户端 <code>mc</code>。mc 兼容 S3 协议，MinIO、AWS S3、阿里云 OSS 都能管。这篇是我的实战笔记，参考了<a href=\"https://docs.hickercity.com/docs/knowledge/mc\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">这份 mc 使用指南</a>补充完善，按使用频率从高到低组织。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"安装与配置\">安装与配置<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE\" class=\"hash-link\" aria-label=\"安装与配置的直接链接\" title=\"安装与配置的直接链接\" translate=\"no\">​</a></h2>\n<p>mc 是单二进制，下下来就能跑：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># Linux</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-o</span><span class=\"token plain\"> /usr/local/bin/mc https://dl.min.io/client/mc/release/linux-amd64/mc </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&amp;&amp;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">chmod</span><span class=\"token plain\"> +x /usr/local/bin/mc</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># macOS</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">brew </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">install</span><span class=\"token plain\"> minio/stable/mc</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 或者容器里临时用一次（不落地配置）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--rm</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-it</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--entrypoint</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token plain\">/bin/sh minio/mc</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--version</span><span class=\"token plain\">   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 验证</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>第一步永远是注册集群别名（alias），后面的命令都用别名指代集群：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">alias</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">set</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\"> http://127.0.0.1:9000 minioadmin minioadmin</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\">#           ^别名  ^服务地址            ^AccessKey  ^SecretKey</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">alias</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">ls</span><span class=\"token plain\">              </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 看已配置的别名</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">alias</span><span class=\"token plain\"> remove </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 删除别名</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin info </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 验证连通性，顺便看集群概况</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>连接非 MinIO 的 S3 服务或个别老环境时，可能需要显式指定签名版本：<code>mc alias set ... --api S3v4</code>（S3v4 是常见默认）。</p>\n<div class=\"theme-admonition theme-admonition-warning admonition_IR7P alert alert--warning\"><div class=\"admonitionHeading_kAub\"><span class=\"admonitionIcon_OBob\"><svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z\"></path></svg></span>凭据安全</div><div class=\"admonitionContent_QYvi\"><p>别把 AccessKey / SecretKey 写进公开仓库。生产环境走环境变量或 CI 密钥注入，并按需收缩账号权限。</p></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"日常操作速查\">日常操作速查<a href=\"https://cooree.co/blog/minio-mc-commands#%E6%97%A5%E5%B8%B8%E6%93%8D%E4%BD%9C%E9%80%9F%E6%9F%A5\" class=\"hash-link\" aria-label=\"日常操作速查的直接链接\" title=\"日常操作速查的直接链接\" translate=\"no\">​</a></h2>\n<table><thead><tr><th>操作</th><th>命令</th></tr></thead><tbody><tr><td>建桶 / 删空桶</td><td><code>mc mb local/photos</code> / <code>mc rb local/photos</code></td></tr><tr><td>看桶列表 / 递归列对象</td><td><code>mc ls local</code> / <code>mc ls --recursive local/photos</code></td></tr><tr><td>上传 / 下载</td><td><code>mc cp app.tar.gz local/backup/</code> / <code>mc cp local/backup/app.tar.gz ./</code></td></tr><tr><td>递归上传目录</td><td><code>mc cp --recursive ./dist local/static/</code></td></tr><tr><td>远端桶间复制</td><td><code>mc cp local/backup/app.log local/archive/app.log</code></td></tr><tr><td>查看对象元数据</td><td><code>mc stat local/backup/app.log</code></td></tr><tr><td>直接看内容 / 看开头</td><td><code>mc cat local/config/app.yaml</code> / <code>mc head local/backup/big.log</code></td></tr><tr><td>比对两端差异</td><td><code>mc diff ./data local/backup/data/</code></td></tr><tr><td>删除对象</td><td><code>mc rm local/photos/old.png</code></td></tr><tr><td>递归删整个前缀</td><td><code>mc rm --recursive --force local/photos/2023/</code></td></tr><tr><td>看占用</td><td><code>mc du local</code> / <code>mc du --depth 2 local</code></td></tr><tr><td>按名字查找</td><td><code>mc find local/photos --name \"*.png\"</code></td></tr></tbody></table>\n<p>几乎所有子命令都支持 <code>--json</code> 输出，配 <code>jq</code> 做脚本解析很方便：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">stat</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--json</span><span class=\"token plain\"> local/backup/app.log </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> jq </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">'.size'</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"桶管理的几个实用参数\">桶管理的几个实用参数<a href=\"https://cooree.co/blog/minio-mc-commands#%E6%A1%B6%E7%AE%A1%E7%90%86%E7%9A%84%E5%87%A0%E4%B8%AA%E5%AE%9E%E7%94%A8%E5%8F%82%E6%95%B0\" class=\"hash-link\" aria-label=\"桶管理的几个实用参数的直接链接\" title=\"桶管理的几个实用参数的直接链接\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 幂等创建：桶已存在也不报错，写进部署脚本里很合适</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mb local/backup --ignore-existing</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 创建时指定区域</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mb local/backup </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--region</span><span class=\"token plain\"> us-east-1</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>删桶有个高危操作单独强调：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 强制删除桶及桶内全部内容，不可恢复，生产慎用</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> rb </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--force</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--dangerous</span><span class=\"token plain\"> local/backup</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"传输的细节参数\">传输的细节参数<a href=\"https://cooree.co/blog/minio-mc-commands#%E4%BC%A0%E8%BE%93%E7%9A%84%E7%BB%86%E8%8A%82%E5%8F%82%E6%95%B0\" class=\"hash-link\" aria-label=\"传输的细节参数的直接链接\" title=\"传输的细节参数的直接链接\" translate=\"no\">​</a></h2>\n<p><code>mc cp</code> / <code>mc mv</code> 有几个容易忽略但很实用的参数：</p>\n<ul>\n<li class=\"\"><code>--attr key=value</code>：上传时附加自定义元数据（如缓存策略、内容类型）</li>\n<li class=\"\"><code>--continue</code>：大文件传断了后续传，不用从头再来</li>\n<li class=\"\"><code>--newer-than 7d</code> / <code>--older-than 30d</code>：按修改时间过滤，只传某时间窗的对象</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"同步mirror与比对diff\">同步（mirror）与比对（diff）<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%90%8C%E6%AD%A5mirror%E4%B8%8E%E6%AF%94%E5%AF%B9diff\" class=\"hash-link\" aria-label=\"同步（mirror）与比对（diff）的直接链接\" title=\"同步（mirror）与比对（diff）的直接链接\" translate=\"no\">​</a></h2>\n<p>备份迁移的核心命令组合：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 增量同步本地目录进桶（默认只增不删）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mirror </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--overwrite</span><span class=\"token plain\"> ./备份目录 local/backup/</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 同步前先看两端差异，心里有数再动手</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">diff</span><span class=\"token plain\"> ./备份目录 local/backup/</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 排除临时文件</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mirror </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--overwrite</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--exclude</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"*.tmp\"</span><span class=\"token plain\"> ./data local/backup/data/</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 加 --watch 持续监听，文件一变就同步（准实时热备）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mirror </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--watch</span><span class=\"token plain\"> ./logs local/log-backup/</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 严格镜像：目标端多出来的文件也删掉（慎用）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> mirror </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--overwrite</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--remove</span><span class=\"token plain\"> ./data local/backup/data/</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>我的经验是：<strong>mirror 之前先 diff</strong>。diff 只读不写，把「将会发生什么」先看清楚，尤其是打算加 <code>--remove</code> 的时候。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"清理旧数据\">清理旧数据<a href=\"https://cooree.co/blog/minio-mc-commands#%E6%B8%85%E7%90%86%E6%97%A7%E6%95%B0%E6%8D%AE\" class=\"hash-link\" aria-label=\"清理旧数据的直接链接\" title=\"清理旧数据的直接链接\" translate=\"no\">​</a></h2>\n<p>按时间过滤删除是定期清理任务的标配：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 清理 30 天前的临时文件</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">rm</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--recursive</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--force</span><span class=\"token plain\"> --older-than 30d local/backup/tmp/</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 开了版本控制的桶，要删干净得加 --versions</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">rm</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--recursive</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--force</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--versions</span><span class=\"token plain\"> local/photos/2023/</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"预签名分享链接\">预签名分享链接<a href=\"https://cooree.co/blog/minio-mc-commands#%E9%A2%84%E7%AD%BE%E5%90%8D%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5\" class=\"hash-link\" aria-label=\"预签名分享链接的直接链接\" title=\"预签名分享链接的直接链接\" translate=\"no\">​</a></h2>\n<p>不给人开账号，发文件/收文件都靠预签名 URL：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 临时下载链接，24 小时有效</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> share download </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--expire</span><span class=\"token plain\"> 24h local/backup/report.pdf</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 临时上传链接，让对方往指定位置传文件</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> share upload </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--expire</span><span class=\"token plain\"> 7d local/incoming/</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>注意 <code>--expire</code> 最长 7 天，写更长会被截断。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"匿名访问权限\">匿名访问权限<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%8C%BF%E5%90%8D%E8%AE%BF%E9%97%AE%E6%9D%83%E9%99%90\" class=\"hash-link\" aria-label=\"匿名访问权限的直接链接\" title=\"匿名访问权限的直接链接\" translate=\"no\">​</a></h2>\n<p>按桶/前缀控制，四档策略：</p>\n<table><thead><tr><th>策略</th><th>说明</th></tr></thead><tbody><tr><td><code>download</code></td><td>匿名可读可下载（静态资源桶常用）</td></tr><tr><td><code>upload</code></td><td>匿名可上传（一般不推荐）</td></tr><tr><td><code>public</code></td><td>匿名可读可写（极度危险，仅测试）</td></tr><tr><td><code>none</code></td><td>禁止匿名访问（默认，最安全）</td></tr></tbody></table>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> anonymous </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">set</span><span class=\"token plain\"> download local/public-assets   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 公开只读</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> anonymous </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">set</span><span class=\"token plain\"> none local/private             </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 关闭匿名</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> anonymous list </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">                         </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 查看各桶现状</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"find-进阶与-mc-admin\">find 进阶与 mc admin<a href=\"https://cooree.co/blog/minio-mc-commands#find-%E8%BF%9B%E9%98%B6%E4%B8%8E-mc-admin\" class=\"hash-link\" aria-label=\"find 进阶与 mc admin的直接链接\" title=\"find 进阶与 mc admin的直接链接\" translate=\"no\">​</a></h2>\n<p><code>mc find</code> 不只是按名字找，还能按时间、大小过滤，甚至对结果执行命令：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">find</span><span class=\"token plain\"> local/backup </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--name</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"*.log\"</span><span class=\"token plain\"> --older-than 7d   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 7 天前的日志</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">find</span><span class=\"token plain\"> local/backup </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--larger</span><span class=\"token plain\"> 100MB                   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 排查异常大文件</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">find</span><span class=\"token plain\"> local/logs </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--name</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"*.gz\"</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--exec</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"mc rm {}\"</span><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 找到即处理</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><code>mc admin</code> 是集群管理入口（需要管理员凭据的 alias）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin info </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">                        </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 集群状态、容量、在线节点</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin user </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">add</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\"> reader pass123456  </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 加用户</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin policy attach </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\"> readwrite </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--user</span><span class=\"token plain\"> reader   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 授权</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">service</span><span class=\"token plain\"> restart </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">             </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 滚动重启</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mc</span><span class=\"token plain\"> admin heal </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--recursive</span><span class=\"token plain\"> </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">local</span><span class=\"token plain\">            </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 触发修复（换盘之后）</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"常见问题\">常见问题<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98\" class=\"hash-link\" aria-label=\"常见问题的直接链接\" title=\"常见问题的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>Access Denied</strong>：先查 AccessKey/SecretKey，再查该账号对目标桶的 IAM/Policy 权限；还有一个隐蔽原因——服务器时间偏差太大会导致签名失败，确认 NTP 正常</li>\n<li class=\"\"><strong>路径写成 <code>s3://bucket/...</code> 报错</strong>：mc 用的是 <code>ALIAS/BUCKET/OBJECT</code> 形式，不是 AWS CLI 的 <code>s3://</code> 写法</li>\n<li class=\"\"><strong>HTTPS 自签名证书报错</strong>：测试环境可临时跳过校验，生产正确做法是把 CA 证书装进系统信任链</li>\n<li class=\"\"><strong>大文件上传中断</strong>：用 <code>mc cp --continue</code> 续传，或改 <code>mirror</code> 增量同步；先 <code>mc du</code> 确认磁盘和桶配额充足</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"几个坑\">几个坑<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"几个坑的直接链接\" title=\"几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>mirror 默认不删多余文件</strong>：源端删了的目标端还在，想完全一致必须显式加 <code>--remove</code>；加了 <code>--remove</code> 就有破坏性，先拿测试桶练手</li>\n<li class=\"\"><strong>mc 和服务端版本要般配</strong>：太老的 mc 连新服务端会在 admin 子命令上报怪错，升级 mc 就好</li>\n<li class=\"\"><strong><code>mc rm --recursive --force</code> 没有回收站</strong>：删了就是删了，删之前先 <code>mc ls --recursive</code> 确认范围，或先 mirror 一份备份</li>\n<li class=\"\"><strong><code>--force</code> 与 <code>--dangerous</code> 成对出现的地方都要当心</strong>：比如删非空桶，二次确认被跳过</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/minio-mc-commands#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>mc 的设计很「Unix」：<code>ls</code>、<code>cp</code>、<code>rm</code>、<code>cat</code>、<code>du</code>、<code>find</code> 一套照搬，学习成本约等于零。日常运维记住 <code>alias set</code> 起手、<code>diff</code> 先行、<code>mirror</code> 做同步、<code>share</code> 发链接、<code>admin info</code> 看集群，就覆盖了九成场景。剩下的翻翻 <code>mc &lt;命令&gt; --help</code>，自带的帮助写得相当清楚。</p>",
            "url": "https://cooree.co/blog/minio-mc-commands",
            "title": "MinIO 运维日常：mc 命令实战笔记",
            "summary": "MinIO 官方客户端 mc 的安装配置、桶管理、传输同步、差异比对、预签名链接、权限策略与常见问题，一篇覆盖日常运维。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "MinIO",
                "对象存储",
                "运维"
            ]
        },
        {
            "id": "https://cooree.co/blog/nsenter-container-debug",
            "content_html": "<p>生产容器基本都是精简镜像，里面没有 <code>ss</code>、<code>tcpdump</code>，甚至没 <code>sh</code>。想抓个包、看个端口，总不能往运行中的容器里装东西。<code>nsenter</code> 是这类场景的救星：<strong>从宿主机直接进入容器的命名空间执行命令</strong>，容器里缺工具也没关系——用的是宿主机的。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"原理一句话\">原理一句话<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%8E%9F%E7%90%86%E4%B8%80%E5%8F%A5%E8%AF%9D\" class=\"hash-link\" aria-label=\"原理一句话的直接链接\" title=\"原理一句话的直接链接\" translate=\"no\">​</a></h2>\n<p>容器隔离的本质是 Linux namespace。<code>nsenter</code> 是对 <code>setns</code> 系统调用的封装：指定一个目标进程的 PID，把当前命令「塞进」它的某个命名空间里执行。容器里 1 号进程的所有命名空间就是这个容器的隔离边界，进去就等于站在容器内部。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"基本用法\">基本用法<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95\" class=\"hash-link\" aria-label=\"基本用法的直接链接\" title=\"基本用法的直接链接\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token plain\">PID</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">[</span><span class=\"token plain\">命名空间选项</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token plain\">要执行的命令</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>常用命名空间选项：</p>\n<table><thead><tr><th>选项</th><th>进入的空间</th><th>典型用途</th></tr></thead><tbody><tr><td><code>-n</code></td><td>network</td><td>抓包、看端口、看路由（用得最多）</td></tr><tr><td><code>-m</code></td><td>mount</td><td>看容器视角的文件系统挂载</td></tr><tr><td><code>-p</code></td><td>pid</td><td>看容器内的进程列表</td></tr><tr><td><code>-i</code></td><td>ipc</td><td>共享内存、消息队列</td></tr><tr><td><code>-u</code></td><td>uts</td><td>主机名</td></tr><tr><td><code>-a</code></td><td>全部</td><td>完全进入容器环境</td></tr></tbody></table>\n<p>也可以不通过 PID、直接指定命名空间文件，比如 Kubernetes 注册的：<code>nsenter --net=/var/run/netns/cni-xxx ...</code></p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"先拿到容器的-pid\">先拿到容器的 PID<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%85%88%E6%8B%BF%E5%88%B0%E5%AE%B9%E5%99%A8%E7%9A%84-pid\" class=\"hash-link\" aria-label=\"先拿到容器的 PID的直接链接\" title=\"先拿到容器的 PID的直接链接\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># Docker</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">PID</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$(</span><span class=\"token variable function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> inspect </span><span class=\"token variable parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-f</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> </span><span class=\"token variable string\" style=\"color:hsl(119, 34%, 47%)\">'{{.State.Pid}}'</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> </span><span class=\"token variable operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">容器名</span><span class=\"token variable operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># Kubernetes 节点上（找 Pod 沙箱的 PID）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">crictl pods </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--name</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token plain\">pod名</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><span class=\"token plain\">           </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 拿到 pod 沙箱 ID</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">crictl inspect </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token plain\">沙箱ID</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">grep</span><span class=\"token plain\"> pid   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 里面的 info.pid</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>K8s 里一个 Pod 的所有容器共享网络命名空间，所以<strong>进 pause 沙箱的网络空间就等于进了整个 Pod 的网络</strong>。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"实战场景\">实战场景<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%AE%9E%E6%88%98%E5%9C%BA%E6%99%AF\" class=\"hash-link\" aria-label=\"实战场景的直接链接\" title=\"实战场景的直接链接\" translate=\"no\">​</a></h2>\n<p><strong>抓容器网卡的包</strong>（最经典，配合 <a class=\"\" href=\"https://cooree.co/blog/tcpdump-practical-notes\">tcpdump 笔记</a>一起看）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-n</span><span class=\"token plain\"> tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> eth0 </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">80</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>看容器里实际监听的端口</strong>（镜像里没 <code>ss</code> 时）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-n</span><span class=\"token plain\"> ss </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-lnt</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>看容器视角的挂载和磁盘</strong>：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-m</span><span class=\"token plain\"> -- </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">df</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-h</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-m</span><span class=\"token plain\"> -- </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mount</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">grep</span><span class=\"token plain\"> nfs</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>验证容器内 DNS 解析</strong>：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-n</span><span class=\"token plain\"> -- </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">nslookup</span><span class=\"token plain\"> kubernetes.default</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>完全进入容器环境执行一系列命令</strong>（近似 <code>docker exec</code>，但不要求容器里有 shell）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-a</span><span class=\"token plain\"> /bin/bash</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"几个坑\">几个坑<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"几个坑的直接链接\" title=\"几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>需要 root 或 <code>CAP_SYS_ADMIN</code></strong>，普通用户直接跑会 permission denied</li>\n<li class=\"\"><strong>目标进程退出，命名空间就没了</strong>：拿着 PID 正准备进，容器恰好重启，PID 失效，报 <code>setns: cannot set namespace</code>——重新取一次 PID 即可</li>\n<li class=\"\"><strong><code>-m</code> 里别乱动</strong>：在挂载命名空间里 umount 或挂东西影响的是容器本体，只读看看就好</li>\n<li class=\"\">进网络命名空间后看到的 <code>eth0</code> 是<strong>容器的网卡</strong>，和宿主机的 <code>eth0</code> 不是一回事，别抓错方向</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/nsenter-container-debug#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>nsenter 把「容器里没工具」这个借口彻底消灭了：宿主机的 tcpdump、ss、ip、nslookup 全都是容器的排查工具。记住核心三板斧——<code>docker inspect</code> 拿 PID、<code>nsenter -t $PID -n</code> 进网络空间、完事退出不留痕。它比进容器装调试镜像优雅得多，也不会污染运行环境。</p>",
            "url": "https://cooree.co/blog/nsenter-container-debug",
            "title": "nsenter：不装工具也能排查容器内部",
            "summary": "用 nsenter 借用宿主机的工具进入容器的命名空间排查问题，不用往容器里装任何东西。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "Docker",
                "Kubernetes",
                "排查",
                "nsenter"
            ]
        },
        {
            "id": "https://cooree.co/blog/nvm-install-and-mirror",
            "content_html": "<p>前端项目的 Node 版本要求五花八门：老项目锁 Node 16，新项目要 Node 20+，CI 镜像又是另一个版本。系统包管理器装的 Node 只有一个版本，来回卸载重装不现实。nvm 就是干这个的：把多个 Node 版本装进用户目录，一条命令切换。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"安装\">安装<a href=\"https://cooree.co/blog/nvm-install-and-mirror#%E5%AE%89%E8%A3%85\" class=\"hash-link\" aria-label=\"安装的直接链接\" title=\"安装的直接链接\" translate=\"no\">​</a></h2>\n<p>官方安装脚本（版本号以 <a href=\"https://github.com/nvm-sh/nvm/releases\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">nvm  releases 页</a>为准，写这篇时最新是 v0.40.8）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">bash</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>脚本做的事很简单：把 nvm 克隆到 <code>~/.nvm</code>，然后往你的 <code>~/.bashrc</code> / <code>~/.zshrc</code> 里追加几行初始化代码。装完<strong>重开终端</strong>或手动生效：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">source</span><span class=\"token plain\"> ~/.bashrc   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># zsh 用户用 ~/.zshrc</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--version</span><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 能打印出版本号就成了</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<div class=\"theme-admonition theme-admonition-warning admonition_IR7P alert alert--warning\"><div class=\"admonitionHeading_kAub\"><span class=\"admonitionIcon_OBob\"><svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z\"></path></svg></span>国内网络</div><div class=\"admonitionContent_QYvi\"><p>安装脚本要访问 <code>raw.githubusercontent.com</code>，国内大概率超时。三个替代办法，任选其一：</p><div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 1. 走代理（有的话）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">https_proxy</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token plain\">http://127.0.0.1:7890 </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">bash</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 2. 直接下 tarball 解压到 ~/.nvm</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">mkdir</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-p</span><span class=\"token plain\"> ~/.nvm </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&amp;&amp;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-L</span><span class=\"token plain\"> https://github.com/nvm-sh/nvm/archive/refs/tags/v0.40.8.tar.gz </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">tar</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-xz</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-C</span><span class=\"token plain\"> ~/.nvm --strip-components</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">1</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 然后手动把初始化代码写进 shell rc（见官方 README）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 3. 用 Gitee 上的同步镜像仓（搜 nvm 镜像，注意甄别同步是否及时）</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"装-node-走国内镜像\">装 Node 走国内镜像<a href=\"https://cooree.co/blog/nvm-install-and-mirror#%E8%A3%85-node-%E8%B5%B0%E5%9B%BD%E5%86%85%E9%95%9C%E5%83%8F\" class=\"hash-link\" aria-label=\"装 Node 走国内镜像的直接链接\" title=\"装 Node 走国内镜像的直接链接\" translate=\"no\">​</a></h2>\n<p>nvm 装好了，装 Node 还要从 nodejs.org 下载，同样慢。把下载源换成 npmmirror：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 写入 shell rc，永久生效</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">export</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">NVM_NODEJS_ORG_MIRROR</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token plain\">https://npmmirror.com/mirrors/node</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>之后再装版本就丝滑了：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">install</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--lts</span><span class=\"token plain\">        </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 装最新 LTS</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">install</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">20</span><span class=\"token plain\">           </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 装指定大版本的最新</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm ls-remote </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--lts</span><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 看看有哪些 LTS</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"日常命令\">日常命令<a href=\"https://cooree.co/blog/nvm-install-and-mirror#%E6%97%A5%E5%B8%B8%E5%91%BD%E4%BB%A4\" class=\"hash-link\" aria-label=\"日常命令的直接链接\" title=\"日常命令的直接链接\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">ls</span><span class=\"token plain\">                   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 本机已装版本</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm use </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">20</span><span class=\"token plain\">               </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 当前 shell 切到 Node 20</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm </span><span class=\"token builtin class-name\" style=\"color:hsl(35, 99%, 36%)\">alias</span><span class=\"token plain\"> default </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">20</span><span class=\"token plain\">     </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 设默认版本（新终端自动用它）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm current              </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 当前在用哪个</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nvm uninstall </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">16</span><span class=\"token plain\">         </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 卸载某个版本</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>项目里放一个 <code>.nvmrc</code> 文件（内容就一行版本号，如 <code>20</code>），进目录后 <code>nvm use</code> 不带参数会自动读它，团队协作时每人手上的版本就统一了。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"几个坑\">几个坑<a href=\"https://cooree.co/blog/nvm-install-and-mirror#%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"几个坑的直接链接\" title=\"几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>新开终端 nvm 失效</strong>：初始化代码没写进你实际用的 shell 的 rc 文件（bash 和 zsh 是两份）。用 <code>echo $SHELL</code> 确认自己跑的是什么 shell</li>\n<li class=\"\"><strong><code>sudo</code> 下 nvm 不存在</strong>：nvm 装在用户目录，root 的环境里没有它。需要全局场景就换思路，别 sudo</li>\n<li class=\"\"><strong>全局 npm 包不共享</strong>：每个 Node 版本有自己独立的全局包目录，切版本后 <code>npm i -g</code> 装过的工具要重装。装完新版本可以用 <code>nvm install 20 --reinstall-packages-from=16</code> 一次性搬过去</li>\n<li class=\"\"><strong>别用 brew 装 nvm</strong>：官方明确不支持，brew 版和初始化脚本经常闹别扭，老老实实走官方脚本</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/nvm-install-and-mirror#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>nvm 本身没什么技术含量，但它是前端环境的第一块地基：装对一次，后面所有项目的版本切换都是一句话的事。国内使用记住两个加速点——安装脚本走代理或镜像，装 Node 前把 <code>NVM_NODEJS_ORG_MIRROR</code> 指到 npmmirror。</p>",
            "url": "https://cooree.co/blog/nvm-install-and-mirror",
            "title": "nvm：Node 版本管理与国内安装加速",
            "summary": "nvm 的安装方式、国内网络下的加速配置和日常命令，以及几个容易踩的坑。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "Node.js",
                "工具",
                "nvm"
            ]
        },
        {
            "id": "https://cooree.co/blog/tcpdump-practical-notes",
            "content_html": "<p>网络问题排查到最后，十有八九要落到「抓个包看看」。tcpdump 是Linux 上抓包的第一工具，参数和表达式看着多，常用的就那一小撮。这篇是我的随手笔记，按「参数 → 表达式 → 菜谱」组织，用的时候直接抄。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"前置\">前置<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E5%89%8D%E7%BD%AE\" class=\"hash-link\" aria-label=\"前置的直接链接\" title=\"前置的直接链接\" translate=\"no\">​</a></h2>\n<p>大多数发行版自带，没有就 <code>apt install tcpdump</code> / <code>yum install tcpdump</code>。抓包需要 root 或 <code>CAP_NET_RAW</code> 能力。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"常用参数速查\">常用参数速查<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E5%B8%B8%E7%94%A8%E5%8F%82%E6%95%B0%E9%80%9F%E6%9F%A5\" class=\"hash-link\" aria-label=\"常用参数速查的直接链接\" title=\"常用参数速查的直接链接\" translate=\"no\">​</a></h2>\n<table><thead><tr><th>参数</th><th>作用</th></tr></thead><tbody><tr><td><code>-i eth0</code> / <code>-i any</code></td><td>指定网卡，<code>any</code> 抓所有（含 lo）</td></tr><tr><td><code>-n</code></td><td>不做 DNS 反解（快很多，基本必加）</td></tr><tr><td><code>-nn</code></td><td>连端口也不反解成服务名（显示 80 而不是 http）</td></tr><tr><td><code>-c 100</code></td><td>抓够 100 个包就停，防止刷屏/打满磁盘</td></tr><tr><td><code>-w file.pcap</code></td><td>写进文件，给 Wireshark 分析</td></tr><tr><td><code>-r file.pcap</code></td><td>从文件读包（可再叠加过滤表达式）</td></tr><tr><td><code>-A</code></td><td>以 ASCII 打印包内容（看 HTTP 明文请求很直观）</td></tr><tr><td><code>-X</code></td><td>同时打印十六进制和 ASCII</td></tr><tr><td><code>-s 0</code></td><td>抓完整包（默认有截断长度，看内容必加）</td></tr><tr><td><code>-q</code></td><td>精简输出，一行一个包</td></tr><tr><td><code>-G 60 -W 10</code></td><td>每 60 秒滚动写一个文件，最多保留 10 个（长期抓包用）</td></tr></tbody></table>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"过滤表达式\">过滤表达式<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E8%BF%87%E6%BB%A4%E8%A1%A8%E8%BE%BE%E5%BC%8F\" class=\"hash-link\" aria-label=\"过滤表达式的直接链接\" title=\"过滤表达式的直接链接\" translate=\"no\">​</a></h2>\n<p>组合规则：<code>and</code>、<code>or</code>、<code>not</code>，加括号分组。</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">host</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">10.0</span><span class=\"token plain\">.0.5                  </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 和这台机器有关的流量</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">src </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">host</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">10.0</span><span class=\"token plain\">.0.5              </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 只看它发出的</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">80</span><span class=\"token plain\">                        </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 端口</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">src port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">53</span><span class=\"token plain\"> and udp            </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 它发出的 DNS 查询</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">net </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">10.244</span><span class=\"token plain\">.0.0/16              </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 整个网段</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">portrange </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">8000</span><span class=\"token plain\">-9000            </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 端口范围</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">icmp                           </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 只看 ICMP（ping）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">[</span><span class=\"token plain\">tcpflags</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&amp;</span><span class=\"token plain\"> tcp-syn </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">!=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">0</span><span class=\"token plain\">   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 只看 SYN（新建连接）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">[</span><span class=\"token plain\">tcpflags</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&amp;</span><span class=\"token plain\"> tcp-rst </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">!=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">0</span><span class=\"token plain\">   </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 只看 RST（被拒/异常断开）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">less</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">1500</span><span class=\"token plain\"> and greater </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">1400</span><span class=\"token plain\">     </span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 按包长过滤（排查 MTU 问题）</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"拿来即用的排查菜谱\">拿来即用的排查菜谱<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E6%8B%BF%E6%9D%A5%E5%8D%B3%E7%94%A8%E7%9A%84%E6%8E%92%E6%9F%A5%E8%8F%9C%E8%B0%B1\" class=\"hash-link\" aria-label=\"拿来即用的排查菜谱的直接链接\" title=\"拿来即用的排查菜谱的直接链接\" translate=\"no\">​</a></h2>\n<p><strong>「服务通不通」先看握手</strong>——只有 SYN 没有 ACK，多半是对面没监听或中间被丢：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> any </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">'tcp[tcpflags] &amp; (tcp-syn|tcp-ack) != 0 and port 8080'</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>抓 HTTP 请求明文看内容</strong>：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> any </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-A</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-s</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">0</span><span class=\"token plain\"> port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">80</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>看 DNS 解析走向</strong>（K8s 里排查 CoreDNS 特别好用）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> any </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">53</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>「小包通、大包卡死」——MTU 黑洞排查</strong>：症状很典型——能 ping 通、能建连、小响应正常，一传大文件就卡死，跨隧道（WireGuard / IPsec / VXLAN）链路最常见。隧道把 MTU 吃小了，而路径上的 ICMP「需要分片」通知又被防火墙吞了，大包发出去就石沉大海。</p>\n<p>先在发大文件的一侧看大包是不是在反复重传：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> eth0 </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">'tcp and greater 1400'</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">host</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&lt;</span><span class=\"token plain\">对端IP</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">&gt;</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 同样的序列号一遍遍出现 = 大包根本没被对面收到</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>再到隧道接口上看有没有人提醒我们降包长：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> tun0 </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> icmp</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 能看到 \"ICMP unreachable - need to frag\" = 通知在路上，只是被中间吞了</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 完全看不到 = 黑洞实锤</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>确认后给 TCP 连接钳制 MSS，让包长不越线即可解决：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">iptables </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> mangle </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-A</span><span class=\"token plain\"> POSTROUTING </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-p</span><span class=\"token plain\"> tcp --tcp-flags SYN,RST SYN </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-j</span><span class=\"token plain\"> TCPMSS --clamp-mss-to-pmtu</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>写文件回去用 Wireshark 细读</strong>：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> any </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-s</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">0</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-w</span><span class=\"token plain\"> /tmp/api.pcap </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">host</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">10.0</span><span class=\"token plain\">.0.5 and port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">443</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-c</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">1000</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>抓容器网卡的包</strong>：容器里没 tcpdump，从宿主机借——先 <code>docker inspect</code> 拿 PID 再 <a class=\"\" href=\"https://cooree.co/blog/nsenter-container-debug\">nsenter</a> 进网络空间：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">PID</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$(</span><span class=\"token variable function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> inspect </span><span class=\"token variable parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-f</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> </span><span class=\"token variable string\" style=\"color:hsl(119, 34%, 47%)\">'{{.State.Pid}}'</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\"> myapp</span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">nsenter </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-t</span><span class=\"token plain\"> </span><span class=\"token variable\" style=\"color:hsl(221, 87%, 60%)\">$PID</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-n</span><span class=\"token plain\"> tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> eth0 </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">80</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>长期值守抓偶发问题</strong>（滚动文件 + 限量）：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">tcpdump </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-i</span><span class=\"token plain\"> eth0 </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-nn</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-s</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">0</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-G</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">300</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-W</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">20</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-w</span><span class=\"token plain\"> /tmp/capture-%Y%m%d%H%M%S.pcap port </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">6379</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"几个坑\">几个坑<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"几个坑的直接链接\" title=\"几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>先看 dropped 计数</strong>：结束时 tcpdump 会打印 <code>dropped by kernel</code> 数量，不为 0 说明抓的速率赶不上流量，加过滤表达式收窄或换 <code>-s</code> 减小快照长度</li>\n<li class=\"\"><strong>抓的位置决定看到什么</strong>：容器场景在宿主机 <code>cni0</code>、<code>veth</code> 对、物理网卡上抓到的视角都不一样；跨节点流量在物理网卡上是封装后的包（flannel 是 UDP 4789），想看成色要选对位置</li>\n<li class=\"\"><strong><code>-A</code> 对 TLS 没用</strong>：443 上的内容全是密文，别浪费时间，最多看看 ClientHello 里的 SNI</li>\n<li class=\"\"><strong>生产环境先估量</strong>：高流量网卡上裸跑 <code>tcpdump -i any</code> 等于自杀，永远先加过滤条件和 <code>-c</code> 限量</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/tcpdump-practical-notes#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>tcpdump 的心法就两条：一是<strong>用表达式把范围缩到最小</strong>，问题流量的特征越具体越好；二是<strong>拿不准就 <code>-w</code> 落盘</strong>，丢给 Wireshark 慢慢看比盯着滚屏强。再配合 nsenter 进容器网络空间，容器网络问题也基本通吃。</p>",
            "url": "https://cooree.co/blog/tcpdump-practical-notes",
            "title": "tcpdump 实战笔记：从抓包参数到排查菜谱",
            "summary": "tcpdump 的常用参数、过滤表达式和几个拿来即用的排查菜谱，以及和 nsenter 配合抓容器包的方法。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "Linux",
                "网络",
                "排查",
                "tcpdump"
            ]
        },
        {
            "id": "https://cooree.co/blog/watchtower-auto-update",
            "content_html": "<p>上篇写的 <a class=\"\" href=\"https://cooree.co/blog/autodok-cicd-container-update\">autodok</a> 是「按需触发」派：CI 构建完镜像后 POST 一下，它才去更新容器。这篇写它的对立面——<strong>轮询派</strong>的代表 watchtower：自己定时去问镜像仓库「有没有新镜像」，有就拉下来原地重启容器，全程不需要 CI 参与。</p>\n<p>两种方式没有优劣，只有适不适合，文末给出选型对比。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"项目地址\">项目地址<a href=\"https://cooree.co/blog/watchtower-auto-update#%E9%A1%B9%E7%9B%AE%E5%9C%B0%E5%9D%80\" class=\"hash-link\" aria-label=\"项目地址的直接链接\" title=\"项目地址的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">GitHub：<a href=\"https://github.com/containrrr/watchtower\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">containrrr/watchtower</a>（Go 编写，Apache-2.0 协议）</li>\n<li class=\"\">官方文档：<a href=\"https://containrrr.dev/watchtower/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">containrrr.dev/watchtower</a></li>\n<li class=\"\">Docker Hub：<a href=\"https://hub.docker.com/r/containrrr/watchtower\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">containrrr/watchtower</a></li>\n</ul>\n<p>工作原理一句话：watchtower 挂载 <code>docker.sock</code>，按设定的周期拿着运行中容器的镜像去仓库比对 digest，发现新镜像就拉取，然后<strong>用原来的启动配置</strong>（卷、端口、环境变量）重建容器。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"部署方式\">部署方式<a href=\"https://cooree.co/blog/watchtower-auto-update#%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F\" class=\"hash-link\" aria-label=\"部署方式的直接链接\" title=\"部署方式的直接链接\" translate=\"no\">​</a></h2>\n<p>最简一行跑起来：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-d</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--name</span><span class=\"token plain\"> watchtower </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-v</span><span class=\"token plain\"> /var/run/docker.sock:/var/run/docker.sock </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  containrrr/watchtower</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>实际使用推荐 compose，把常用参数写清楚：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">services</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">watchtower</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> containrrr/watchtower</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">container_name</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> watchtower</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">restart</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> always</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">volumes</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> /var/run/docker.sock</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">/var/run/docker.sock</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">command</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">interval 3600 </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">cleanup </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">rolling</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">restart</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><code>--cleanup</code> 让更新后顺手删掉旧镜像，避免磁盘被旧镜像悄悄吃满；<code>--interval 3600</code> 把默认 24 小时的轮询周期改成 1 小时。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"常用配置速查\">常用配置速查<a href=\"https://cooree.co/blog/watchtower-auto-update#%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE%E9%80%9F%E6%9F%A5\" class=\"hash-link\" aria-label=\"常用配置速查的直接链接\" title=\"常用配置速查的直接链接\" translate=\"no\">​</a></h2>\n<table><thead><tr><th>参数</th><th>作用</th></tr></thead><tbody><tr><td><code>--interval 3600</code></td><td>轮询周期（秒），默认 86400（24 小时）</td></tr><tr><td><code>--schedule \"0 0 4 * * *\"</code></td><td>用 cron 表达式定时（六段式，含秒），与 interval 二选一</td></tr><tr><td><code>--cleanup</code></td><td>更新后删除旧镜像</td></tr><tr><td><code>--rolling-restart</code></td><td>多副本时逐个重启，避免同时断</td></tr><tr><td><code>--monitor-only</code></td><td>只检测不更新，有更新时发通知（生产建议先用这个观察一阵）</td></tr><tr><td><code>--include-stopped</code> / <code>--include-restarting</code></td><td>把停止/重启中的容器也纳入管理</td></tr><tr><td><code>--remove-anonymous-volumes</code></td><td>更新时连带删除匿名卷（注意数据安全）</td></tr><tr><td><code>--run-once</code></td><td>只跑一轮就退出，适合手动执行或定时任务</td></tr><tr><td><code>--label-enable</code></td><td>只管理带 <code>com.centurylinklabs.watchtower.enable=true</code> 标签的容器</td></tr></tbody></table>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"只更新指定容器\">只更新指定容器<a href=\"https://cooree.co/blog/watchtower-auto-update#%E5%8F%AA%E6%9B%B4%E6%96%B0%E6%8C%87%E5%AE%9A%E5%AE%B9%E5%99%A8\" class=\"hash-link\" aria-label=\"只更新指定容器的直接链接\" title=\"只更新指定容器的直接链接\" translate=\"no\">​</a></h2>\n<p>默认管理所有容器，生产上一般要收窄范围。两种姿势：</p>\n<p><strong>命令行点名</strong>：直接在命令末尾写容器名，只管理列出的：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-d</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--name</span><span class=\"token plain\"> watchtower </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-v</span><span class=\"token plain\"> /var/run/docker.sock:/var/run/docker.sock </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">\\</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  containrrr/watchtower myapp nginx </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">--interval</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">3600</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><strong>标签过滤</strong>（推荐，配合 <code>--label-enable</code>）：只动显式打标的容器，新增容器默认不受管，最安全：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">services</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">myapp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> registry.example.com/myapp</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">latest</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">labels</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> com.centurylinklabs.watchtower.enable=true</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>反过来，给容器打 <code>com.centurylinklabs.watchtower.enable=false</code> 可以明确排除。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"更新通知\">更新通知<a href=\"https://cooree.co/blog/watchtower-auto-update#%E6%9B%B4%E6%96%B0%E9%80%9A%E7%9F%A5\" class=\"hash-link\" aria-label=\"更新通知的直接链接\" title=\"更新通知的直接链接\" translate=\"no\">​</a></h2>\n<p>更新动作发生在凌晨四点而你毫不知情，出了问题就是事故。watchtower 内置 <a href=\"https://containrrr.dev/shoutrrr/v0.8/services/overview\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">shoutrrr</a> 通知，配置一个 URL 即可，支持 Slack、Discord、Gotify、邮件 SMTP、Microsoft Teams、Telegram、ntfy 等几十种渠道，多个地址空格分隔：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">environment</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> WATCHTOWER_NOTIFICATION_URL=slack</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">//watchtower@token</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">a/token</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">b/token</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">c gotify</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">//gotify.example.com/token</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>配合 <code>--notification-title-tag</code> 加标题前缀，多台机器跑多个 watchtower 时能分清通知来自哪台。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"http-api-模式也能被-ci-触发\">HTTP API 模式：也能被 CI 触发<a href=\"https://cooree.co/blog/watchtower-auto-update#http-api-%E6%A8%A1%E5%BC%8F%E4%B9%9F%E8%83%BD%E8%A2%AB-ci-%E8%A7%A6%E5%8F%91\" class=\"hash-link\" aria-label=\"HTTP API 模式：也能被 CI 触发的直接链接\" title=\"HTTP API 模式：也能被 CI 触发的直接链接\" translate=\"no\">​</a></h2>\n<p>很多人不知道 watchtower 也有按需触发的一面。开启 HTTP API 模式后，它暴露 <code>POST /v1/update</code> 端点，外部（比如 CI 流水线）可以主动触发更新：</p>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">services</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">watchtower</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">image</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> containrrr/watchtower</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">volumes</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> /var/run/docker.sock</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\">/var/run/docker.sock</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">command</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">http</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">api</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">update</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">environment</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> WATCHTOWER_HTTP_API_TOKEN=mytoken</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">ports</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\"> 8080</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token number\" style=\"color:hsl(35, 99%, 36%)\">8080</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 触发所有受管容器的更新</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-H</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"Authorization: Bearer mytoken\"</span><span class=\"token plain\"> localhost:8080/v1/update</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 只更新指定镜像</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-H</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"Authorization: Bearer mytoken\"</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(119, 34%, 47%)\">\"localhost:8080/v1/update?image=foo/bar,foo/baz\"</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>注意：<strong>开了 API 模式后默认关闭周期轮询</strong>，想两者并存要加 <code>--http-api-periodic-polls</code>。这个设计思路和 autodok 一致——把触发权交还给流水线。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"私有镜像仓库\">私有镜像仓库<a href=\"https://cooree.co/blog/watchtower-auto-update#%E7%A7%81%E6%9C%89%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93\" class=\"hash-link\" aria-label=\"私有镜像仓库的直接链接\" title=\"私有镜像仓库的直接链接\" translate=\"no\">​</a></h2>\n<p>拉私有仓库的镜像需要凭据，两种方式：</p>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 方式一：环境变量</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-e</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">REPO_USER</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token plain\">username </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-e</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:hsl(221, 87%, 60%)\">REPO_PASS</span><span class=\"token operator\" style=\"color:hsl(221, 87%, 60%)\">=</span><span class=\"token plain\">password</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 方式二：挂载 docker login 后的 config.json（推荐）</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-v</span><span class=\"token plain\"> </span><span class=\"token environment constant\" style=\"color:hsl(35, 99%, 36%)\">$HOME</span><span class=\"token plain\">/.docker/config.json:/config.json</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>方式二有个坑：bind mount 绑定的是 inode，<code>docker login</code> 或编辑器保存文件时是「新建再替换」，inode 变了，容器里的凭据就停留在旧版本。<strong>解决办法是挂软链接</strong>——先 <code>ln -s ~/.docker/config.json ~/docker-config.json</code>，再挂载软链接，inode 就稳定了。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"实践中的几个坑\">实践中的几个坑<a href=\"https://cooree.co/blog/watchtower-auto-update#%E5%AE%9E%E8%B7%B5%E4%B8%AD%E7%9A%84%E5%87%A0%E4%B8%AA%E5%9D%91\" class=\"hash-link\" aria-label=\"实践中的几个坑的直接链接\" title=\"实践中的几个坑的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>生产慎用全自动</strong>：数据库、有状态服务不要交给 watchtower 自动更新，镜像一换数据面就重建，滚动更新和备份策略都不是它的职责。这类服务打 <code>enable=false</code> 排除掉</li>\n<li class=\"\"><strong>先 monitor-only 观察</strong>：上线初用 <code>--monitor-only</code> + 通知跑一两周，确认更新频率和对象符合预期再开自动更新</li>\n<li class=\"\"><strong>cleanup 是把双刃剑</strong>：删旧镜像省磁盘，但出问题时少了「秒回滚旧镜像」这条路。重要服务可以不开 cleanup，改靠定期 <code>docker image prune</code></li>\n<li class=\"\"><strong>生命周期钩子</strong>：需要在更新前执行备份/排空流量等操作，可以看官方文档的 lifecycle hooks，给容器配 <code>pre-update</code>/<code>post-update</code> 命令</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"watchtower-vs-autodok-选型\">watchtower vs autodok 选型<a href=\"https://cooree.co/blog/watchtower-auto-update#watchtower-vs-autodok-%E9%80%89%E5%9E%8B\" class=\"hash-link\" aria-label=\"watchtower vs autodok 选型的直接链接\" title=\"watchtower vs autodok 选型的直接链接\" translate=\"no\">​</a></h2>\n<table><thead><tr><th>维度</th><th>watchtower（轮询）</th><th>autodok（按需）</th></tr></thead><tbody><tr><td>触发方式</td><td>自己定期查仓库</td><td>等 CI POST <code>/update</code></td></tr><tr><td>更新时机</td><td>有延迟（取决于轮询周期）</td><td>精确到「这次构建」</td></tr><tr><td>CI 依赖</td><td>无，仓库里有新镜像就动</td><td>需要流水线里加一步</td></tr><tr><td>通知能力</td><td>内置 shoutrrr 多渠道</td><td>无（看 CI 自己的通知）</td></tr><tr><td>适用场景</td><td>个人服务、第三方镜像跟进、无 CI 的小项目</td><td>有完整 CI/CD、要求更新时机精确的环境</td></tr></tbody></table>\n<p>两者不互斥：我自己的用法是<strong>生产用 autodok 跟着流水线走，个人小服务用 watchtower 开着 label 过滤自动跟进</strong>。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"小结\">小结<a href=\"https://cooree.co/blog/watchtower-auto-update#%E5%B0%8F%E7%BB%93\" class=\"hash-link\" aria-label=\"小结的直接链接\" title=\"小结的直接链接\" translate=\"no\">​</a></h2>\n<p>watchtower 的价值在于「零接入成本」：挂个 socket、起个容器，存量服务立刻获得自动更新能力。代价是更新时机的控制权不在你手里。用 label 过滤收窄管理范围、配上通知渠道、重要服务坚决排除，它就是一个省心的守夜人。</p>",
            "url": "https://cooree.co/blog/watchtower-auto-update",
            "title": "watchtower：让容器自动跟上镜像更新",
            "summary": "watchtower 通过轮询镜像仓库自动更新运行中的容器。记录它的部署方式、常用配置、通知渠道和 HTTP API 触发模式，并与 autodok 做选型对比。",
            "date_modified": "2026-10-24T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "Docker",
                "自动化运维",
                "watchtower",
                "CI/CD"
            ]
        },
        {
            "id": "https://cooree.co/blog/blog-writing-example",
            "content_html": "<p>这是一篇可复制的博客写作示例。博客适合记录运维实践、故障复盘和学习心得；系统化的技术手册可以放在 docs 目录中。</p>\n<!-- -->\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"文件应该放在哪里\">文件应该放在哪里<a href=\"https://cooree.co/blog/blog-writing-example#%E6%96%87%E4%BB%B6%E5%BA%94%E8%AF%A5%E6%94%BE%E5%9C%A8%E5%93%AA%E9%87%8C\" class=\"hash-link\" aria-label=\"文件应该放在哪里的直接链接\" title=\"文件应该放在哪里的直接链接\" translate=\"no\">​</a></h2>\n<p>文章放在项目根目录的 <code>blog/</code> 下，也可以按主题建立子目录，例如 <code>blog/containers/docker-inspection.md</code>。使用 <code>.md</code> 或 <code>.mdx</code> 文件，开头写 YAML 元信息，后面写 Markdown 正文。</p>\n<p>目录用于整理源文件，不会自动成为 Navbar 分类。本文设置了 <code>slug: blog-writing-example</code>，对应地址是 <code>/blog/blog-writing-example</code>。复制本文件后，请修改标题、日期、摘要和 slug，避免地址重复。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"文章元信息\">文章元信息<a href=\"https://cooree.co/blog/blog-writing-example#%E6%96%87%E7%AB%A0%E5%85%83%E4%BF%A1%E6%81%AF\" class=\"hash-link\" aria-label=\"文章元信息的直接链接\" title=\"文章元信息的直接链接\" translate=\"no\">​</a></h2>\n<div class=\"language-yaml codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-yaml codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">---</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">slug</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> docker</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">-</span><span class=\"token plain\">inspection</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">title</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> Docker 日常巡检记录</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">date</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> </span><span class=\"token datetime number\" style=\"color:hsl(35, 99%, 36%)\">2026-10-21</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">authors</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> ops</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">tags</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">[</span><span class=\"token plain\">Docker</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">,</span><span class=\"token plain\"> 运维</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">keywords</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">[</span><span class=\"token plain\">Docker</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">,</span><span class=\"token plain\"> 容器</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">,</span><span class=\"token plain\"> 巡检</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:hsl(35, 99%, 36%)\">description</span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">:</span><span class=\"token plain\"> 记录 Docker 容器状态、资源占用和日志的日常检查方法。</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(119, 34%, 47%)\">---</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<table><thead><tr><th>字段</th><th>本站写作建议</th></tr></thead><tbody><tr><td><code>title</code></td><td>明确填写文章标题，正文从二级标题开始即可。</td></tr><tr><td><code>date</code></td><td>明确填写发布日期，使用 <code>YYYY-MM-DD</code>，便于排序和归档。</td></tr><tr><td><code>slug</code></td><td>建议填写唯一的英文短路径，文件改名后也能保持文章地址。</td></tr><tr><td><code>authors</code></td><td>使用 <code>blog/authors.yml</code> 中的作者键；当前示例为 <code>ops</code>。</td></tr><tr><td><code>tags</code></td><td>用数组填写分类标签，供标签页聚合文章。</td></tr><tr><td><code>keywords</code></td><td>可选，填写与文章相关的关键词。</td></tr><tr><td><code>description</code></td><td>建议填写简短描述，用于页面元信息。</td></tr><tr><td><code>image</code></td><td>可选，填写已存在的封面图片路径或有效 URL。</td></tr><tr><td><code>sticky</code></td><td>本模板扩展字段，可选数字；数值越大排序越靠前，省略时按 0 处理。</td></tr><tr><td><code>draft</code></td><td>可选，设为 <code>true</code> 时用于草稿，生产构建不发布。</td></tr></tbody></table>\n<p>这些字段不要求全部填写。本站建议显式填写上面示例中的字段，避免依赖文件名推断标题或日期。YAML 使用空格缩进；包含特殊字符的标题或描述可用引号包裹。</p>\n<p><code>authors.yml</code> 目前使用“容器运维工程师”作为显示名称，可以自行改成昵称，并按需添加个人主页或头像。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"首页与置顶\">首页与置顶<a href=\"https://cooree.co/blog/blog-writing-example#%E9%A6%96%E9%A1%B5%E4%B8%8E%E7%BD%AE%E9%A1%B6\" class=\"hash-link\" aria-label=\"首页与置顶的直接链接\" title=\"首页与置顶的直接链接\" translate=\"no\">​</a></h2>\n<p>博客插件沿用 Docusaurus 的文章处理，在此基础上按 <code>sticky</code> 值降序排列，并将前 10 篇文章提供给首页。需要置顶时，可在元信息中添加 <code>sticky: 1</code>；日常文章可以省略。<code>date</code> 用于发布时间和默认时间排序。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"列表摘要\">列表摘要<a href=\"https://cooree.co/blog/blog-writing-example#%E5%88%97%E8%A1%A8%E6%91%98%E8%A6%81\" class=\"hash-link\" aria-label=\"列表摘要的直接链接\" title=\"列表摘要的直接链接\" translate=\"no\">​</a></h2>\n<p>在开头写一至两段摘要，再插入以下标记。标记前的内容用于博客列表摘要，完整正文仍会显示：</p>\n<div class=\"language-md codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-md codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">{/</span><span class=\"token italic punctuation\" style=\"font-style:italic;color:hsl(119, 34%, 47%)\">*</span><span class=\"token italic content\" style=\"font-style:italic\"> truncate </span><span class=\"token italic punctuation\" style=\"font-style:italic;color:hsl(119, 34%, 47%)\">*</span><span class=\"token plain\">/}</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p><code>description</code> 与列表摘要不是同一个用途，建议同时填写描述和截断标记。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"运维文章正文示例\">运维文章正文示例<a href=\"https://cooree.co/blog/blog-writing-example#%E8%BF%90%E7%BB%B4%E6%96%87%E7%AB%A0%E6%AD%A3%E6%96%87%E7%A4%BA%E4%BE%8B\" class=\"hash-link\" aria-label=\"运维文章正文示例的直接链接\" title=\"运维文章正文示例的直接链接\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"背景与目标\">背景与目标<a href=\"https://cooree.co/blog/blog-writing-example#%E8%83%8C%E6%99%AF%E4%B8%8E%E7%9B%AE%E6%A0%87\" class=\"hash-link\" aria-label=\"背景与目标的直接链接\" title=\"背景与目标的直接链接\" translate=\"no\">​</a></h3>\n<p>记录操作原因、预期结果、适用版本和环境。示例目标是查看 Docker 容器的运行状态，不代表已经对实际环境执行操作。</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"环境与前置条件\">环境与前置条件<a href=\"https://cooree.co/blog/blog-writing-example#%E7%8E%AF%E5%A2%83%E4%B8%8E%E5%89%8D%E7%BD%AE%E6%9D%A1%E4%BB%B6\" class=\"hash-link\" aria-label=\"环境与前置条件的直接链接\" title=\"环境与前置条件的直接链接\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">环境：填写测试或生产环境。</li>\n<li class=\"\">版本：填写 Docker 和操作系统版本。</li>\n<li class=\"\">权限：确认具备访问目标 Docker 服务的权限。</li>\n<li class=\"\">变更窗口：涉及变更时填写时间和影响范围。</li>\n</ul>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"检查步骤\">检查步骤<a href=\"https://cooree.co/blog/blog-writing-example#%E6%A3%80%E6%9F%A5%E6%AD%A5%E9%AA%A4\" class=\"hash-link\" aria-label=\"检查步骤的直接链接\" title=\"检查步骤的直接链接\" translate=\"no\">​</a></h3>\n<div class=\"language-bash codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-bash codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 查看容器及其状态</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">ps</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(221, 87%, 60%)\">-a</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(230, 4%, 64%)\"># 查看一次资源占用快照</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(221, 87%, 60%)\">docker</span><span class=\"token plain\"> stats --no-stream</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>在命令后记录预期输出、实际结果和异常判断依据。日志中如有密码、令牌或内部地址，发布前先处理敏感信息。</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"验证与回滚\">验证与回滚<a href=\"https://cooree.co/blog/blog-writing-example#%E9%AA%8C%E8%AF%81%E4%B8%8E%E5%9B%9E%E6%BB%9A\" class=\"hash-link\" aria-label=\"验证与回滚的直接链接\" title=\"验证与回滚的直接链接\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">验证：记录服务状态、监控指标和业务检查结果。</li>\n<li class=\"\">回滚：若涉及配置变更，写明恢复步骤和验证方法。</li>\n<li class=\"\">本例仅展示查询命令，无需回滚；实际操作请按影响填写。</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"admonitions-提示框\">Admonitions 提示框<a href=\"https://cooree.co/blog/blog-writing-example#admonitions-%E6%8F%90%E7%A4%BA%E6%A1%86\" class=\"hash-link\" aria-label=\"Admonitions 提示框的直接链接\" title=\"Admonitions 提示框的直接链接\" translate=\"no\">​</a></h2>\n<p>采用 Docusaurus 标准语法，类型后可用方括号设置标题，正文与冒号标记之间保留空行：</p>\n<div class=\"language-md codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-md codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">:::tip[操作建议]</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">先在测试环境验证，再执行生产变更。</span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\">:::</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<div class=\"theme-admonition theme-admonition-tip admonition_IR7P alert alert--success\"><div class=\"admonitionHeading_kAub\"><span class=\"admonitionIcon_OBob\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>操作建议</div><div class=\"admonitionContent_QYvi\"><p>先在测试环境验证，再执行生产变更。</p></div></div>\n<div class=\"theme-admonition theme-admonition-warning admonition_IR7P alert alert--warning\"><div class=\"admonitionHeading_kAub\"><span class=\"admonitionIcon_OBob\"><svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z\"></path></svg></span>变更影响</div><div class=\"admonitionContent_QYvi\"><p>执行重启、清理或升级前，确认业务影响、备份和回滚方案。</p></div></div>\n<p>常用类型包括 <code>note</code>、<code>tip</code>、<code>info</code>、<code>warning</code>、<code>danger</code>。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"图片与链接\">图片与链接<a href=\"https://cooree.co/blog/blog-writing-example#%E5%9B%BE%E7%89%87%E4%B8%8E%E9%93%BE%E6%8E%A5\" class=\"hash-link\" aria-label=\"图片与链接的直接链接\" title=\"图片与链接的直接链接\" translate=\"no\">​</a></h2>\n<p>本地图片放在 <code>static/</code> 下，引用时省略 <code>static</code>。下面是语法示例，需要先放入实际图片再使用：</p>\n<div class=\"language-md codeBlockContainer_APcc theme-code-block\" style=\"--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)\"><div class=\"codeBlockContent_m3Ux\"><pre class=\"prism-code language-md codeBlock_qGQc thin-scrollbar\" style=\"background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)\"><code class=\"codeBlockLines_p187\"><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token url operator\" style=\"color:hsl(221, 87%, 60%)\">!</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">[</span><span class=\"token url content\" style=\"color:hsl(198, 99%, 37%)\">容器巡检截图</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">](</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">/img/blog/docker-inspection.png</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:hsl(230, 8%, 24%)\"><span class=\"token plain\"></span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">[</span><span class=\"token url content\" style=\"color:hsl(198, 99%, 37%)\">Docker 官方文档</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">](</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">https://docs.docker.com/</span><span class=\"token url\" style=\"color:hsl(198, 99%, 37%)\">)</span><br></span></code></pre><div class=\"buttonGroup_6DOT\"><button type=\"button\" aria-label=\"复制代码到剪贴板\" title=\"复制\" class=\"clean-btn\"><span class=\"copyButtonIcons_FhaS\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_phi_\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_FfTR\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div>\n<p>Markdown 可以直接写链接、表格、列表和代码块；如需使用 React 组件，再考虑 MDX 和对应的组件导入。</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_ckxH\" id=\"发布前检查\">发布前检查<a href=\"https://cooree.co/blog/blog-writing-example#%E5%8F%91%E5%B8%83%E5%89%8D%E6%A3%80%E6%9F%A5\" class=\"hash-link\" aria-label=\"发布前检查的直接链接\" title=\"发布前检查的直接链接\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">修改 <code>slug</code>、<code>title</code>、<code>date</code>、<code>description</code> 和标签。</li>\n<li class=\"\">确认 <code>authors</code> 能在作者配置中找到。</li>\n<li class=\"\">保留一处摘要截断标记，检查正文和图片链接。</li>\n<li class=\"\">删除示例说明、占位内容和敏感信息。</li>\n<li class=\"\">运行 <code>pnpm dev</code> 查看文章与博客列表。</li>\n<li class=\"\">结束开发服务后运行 <code>pnpm build</code>，检查构建结果。</li>\n</ul>",
            "url": "https://cooree.co/blog/blog-writing-example",
            "title": "博客编写示例：从元信息到运维记录",
            "summary": "本站博客写作模板，说明文章元信息、摘要截断、代码块、图片和提示框的用法。",
            "date_modified": "2026-10-21T00:00:00.000Z",
            "author": {
                "name": "容器运维工程师"
            },
            "tags": [
                "运维",
                "写作指南"
            ]
        }
    ]
}