<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://cooree.co/blog</id>
    <title>新手爱记录</title>
    <updated>2026-10-24T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://cooree.co/blog"/>
    <subtitle>新手爱记录 Blog</subtitle>
    <icon>https://cooree.co/img/favicon.ico</icon>
    <rights>Copyright © 2026 新手爱记录 Built with Docusaurus.</rights>
    <entry>
        <title type="html"><![CDATA[autodok：让 CI 流水线按需更新容器的轻量工具]]></title>
        <id>https://cooree.co/blog/autodok-cicd-container-update</id>
        <link href="https://cooree.co/blog/autodok-cicd-container-update"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[autodok 提供一个 API，按需拉取新镜像并用原配置重启容器。记录它的部署方式，以及和 GitLab CI、Jenkins、curl 手动触发的几种用法。]]></summary>
        <content type="html"><![CDATA[<p>容器更新工具里 watchtower 名气最大，但它的思路是<strong>轮询</strong>：每隔一段时间去问镜像仓库「有没有新镜像」。轮询间隔摆在那里，更新不够即时，还得给它开仓库的读权限。</p>
<p>autodok 走的是另一条路：<strong>不轮询，只等通知</strong>。它暴露一个 HTTP API，CI 流水线构建完新镜像后 POST 一下，它就把镜像拉下来、用原配置重启容器。主动权在流水线手里，更新时机精确到「这次构建」。</p>
<!-- -->
<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>
<ul>
<li class="">GitHub：<a href="https://github.com/cars10/autodok" target="_blank" rel="noopener noreferrer" class="">cars10/autodok</a>（Rust 编写，MIT 协议）</li>
<li class="">Docker Hub：<a href="https://hub.docker.com/r/cars10/autodok" target="_blank" rel="noopener noreferrer" class="">cars10/autodok</a></li>
</ul>
<p>项目非常精简，只暴露两个端点：</p>
<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>
<p>推荐的工作流：</p>
<ol>
<li class="">推送代码触发 CI</li>
<li class="">CI 构建并推送新镜像</li>
<li class="">CI 向 autodok 发 <code>POST /update</code>，带上容器名和新镜像 tag</li>
<li class="">autodok 拉镜像、按原配置（卷、环境变量等）重启容器</li>
</ol>
<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>
<p>用 docker compose 起一个容器就行，官方仓库自带 <code>compose.yml</code>：</p>
<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>
<p>三个关键点：</p>
<ul>
<li class=""><strong>挂载 <code>docker.sock</code></strong>：autodok 靠它操作本机容器，这是它能「重启别的容器」的前提</li>
<li class=""><strong><code>./data</code> 目录</strong>：API Key 持久化在这里，启动后从日志（<code>docker compose logs -f autodok</code>）或 <code>./data/api_key</code> 文件里都能拿到</li>
<li class=""><strong>端口默认注释掉了</strong>：推荐用 nginx / traefik 反代一个域名出来（比如 <code>autodok.example.com</code>），比直接暴露端口好管理，也方便流水线跨机访问</li>
</ul>
<p>如果从私有镜像仓库拉镜像，把最后一行 volume 的注释去掉，挂上你 <code>docker login</code> 过的 <code>config.json</code>，autodok 会复用里面的凭据。</p>
<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>
<p>最朴素的用法，排查问题或临时更新时很实用：</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%)"># 健康检查（不需要鉴权）</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>
<p><code>container</code> 必须是<strong>正在运行中</strong>的容器名；<code>image</code> 必须是仓库里已存在的镜像和 tag。</p>
<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>
<p>在 <code>.gitlab-ci.yml</code> 里，构建推送镜像之后加一个 deploy 阶段：</p>
<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>
<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>
<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>
<p>Jenkinsfile 里同样在推送镜像后加一步：</p>
<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>
<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>
<p>如果装了 HTTP Request 插件，也可以不用 curl，写成声明式：</p>
<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>
<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>
<ul>
<li class=""><strong>超时设置</strong>：<code>POST /update</code> 的耗时 = 拉镜像 + 重启容器。大镜像可能要几分钟，除了 curl 的 <code>--max-time</code>，前面反代（nginx 的 <code>proxy_read_timeout</code>）和 CI 客户端的超时也要同步放大，否则镜像还没拉完请求先断了——注意请求断了不影响 autodok 继续执行，只是你拿不到结果</li>
<li class=""><strong>一次只能更新一个容器</strong>：要更新多个容器就发多个请求，串行执行</li>
<li class=""><strong>API Key 保管</strong>：它等于这台机器容器层的操作权限，别写死在仓库里，一律走 CI 变量/凭据注入</li>
</ul>
<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>
<p>autodok 的功能边界很清晰：不做镜像扫描、不做编排、不轮询，就老老实实提供「给我一个容器名和新镜像，我帮你原地更新」的 API。对「代码 push 后希望测试环境立刻更新」这类场景，比 watchtower 的轮询更精准，也比在流水线里直接 ssh 上去敲命令干净得多。项目很小，源码读完不用一顿饭的时间，值得上手一试。</p>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="Docker" term="Docker"/>
        <category label="CI/CD" term="CI/CD"/>
        <category label="自动化运维" term="自动化运维"/>
        <category label="autodok" term="autodok"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MinIO 运维日常：mc 命令实战笔记]]></title>
        <id>https://cooree.co/blog/minio-mc-commands</id>
        <link href="https://cooree.co/blog/minio-mc-commands"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[MinIO 官方客户端 mc 的安装配置、桶管理、传输同步、差异比对、预签名链接、权限策略与常见问题，一篇覆盖日常运维。]]></summary>
        <content type="html"><![CDATA[<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>
<!-- -->
<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>
<p>mc 是单二进制，下下来就能跑：</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%)"># 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>
<p>第一步永远是注册集群别名（alias），后面的命令都用别名指代集群：</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 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>
<p>连接非 MinIO 的 S3 服务或个别老环境时，可能需要显式指定签名版本：<code>mc alias set ... --api S3v4</code>（S3v4 是常见默认）。</p>
<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>
<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>
<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>
<p>几乎所有子命令都支持 <code>--json</code> 输出，配 <code>jq</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 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>
<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>
<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>
<p>删桶有个高危操作单独强调：</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%)"># 强制删除桶及桶内全部内容，不可恢复，生产慎用</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>
<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>
<p><code>mc cp</code> / <code>mc mv</code> 有几个容易忽略但很实用的参数：</p>
<ul>
<li class=""><code>--attr key=value</code>：上传时附加自定义元数据（如缓存策略、内容类型）</li>
<li class=""><code>--continue</code>：大文件传断了后续传，不用从头再来</li>
<li class=""><code>--newer-than 7d</code> / <code>--older-than 30d</code>：按修改时间过滤，只传某时间窗的对象</li>
</ul>
<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>
<p>备份迁移的核心命令组合：</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%)"># 增量同步本地目录进桶（默认只增不删）</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>
<p>我的经验是：<strong>mirror 之前先 diff</strong>。diff 只读不写，把「将会发生什么」先看清楚，尤其是打算加 <code>--remove</code> 的时候。</p>
<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>
<p>按时间过滤删除是定期清理任务的标配：</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%)"># 清理 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>
<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>
<p>不给人开账号，发文件/收文件都靠预签名 URL：</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%)"># 临时下载链接，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>
<p>注意 <code>--expire</code> 最长 7 天，写更长会被截断。</p>
<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>
<p>按桶/前缀控制，四档策略：</p>
<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>
<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>
<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>
<p><code>mc find</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 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>
<p><code>mc admin</code> 是集群管理入口（需要管理员凭据的 alias）：</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 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>
<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>
<ul>
<li class=""><strong>Access Denied</strong>：先查 AccessKey/SecretKey，再查该账号对目标桶的 IAM/Policy 权限；还有一个隐蔽原因——服务器时间偏差太大会导致签名失败，确认 NTP 正常</li>
<li class=""><strong>路径写成 <code>s3://bucket/...</code> 报错</strong>：mc 用的是 <code>ALIAS/BUCKET/OBJECT</code> 形式，不是 AWS CLI 的 <code>s3://</code> 写法</li>
<li class=""><strong>HTTPS 自签名证书报错</strong>：测试环境可临时跳过校验，生产正确做法是把 CA 证书装进系统信任链</li>
<li class=""><strong>大文件上传中断</strong>：用 <code>mc cp --continue</code> 续传，或改 <code>mirror</code> 增量同步；先 <code>mc du</code> 确认磁盘和桶配额充足</li>
</ul>
<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>
<ul>
<li class=""><strong>mirror 默认不删多余文件</strong>：源端删了的目标端还在，想完全一致必须显式加 <code>--remove</code>；加了 <code>--remove</code> 就有破坏性，先拿测试桶练手</li>
<li class=""><strong>mc 和服务端版本要般配</strong>：太老的 mc 连新服务端会在 admin 子命令上报怪错，升级 mc 就好</li>
<li class=""><strong><code>mc rm --recursive --force</code> 没有回收站</strong>：删了就是删了，删之前先 <code>mc ls --recursive</code> 确认范围，或先 mirror 一份备份</li>
<li class=""><strong><code>--force</code> 与 <code>--dangerous</code> 成对出现的地方都要当心</strong>：比如删非空桶，二次确认被跳过</li>
</ul>
<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>
<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>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="MinIO" term="MinIO"/>
        <category label="对象存储" term="对象存储"/>
        <category label="运维" term="运维"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[nsenter：不装工具也能排查容器内部]]></title>
        <id>https://cooree.co/blog/nsenter-container-debug</id>
        <link href="https://cooree.co/blog/nsenter-container-debug"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[用 nsenter 借用宿主机的工具进入容器的命名空间排查问题，不用往容器里装任何东西。]]></summary>
        <content type="html"><![CDATA[<p>生产容器基本都是精简镜像，里面没有 <code>ss</code>、<code>tcpdump</code>，甚至没 <code>sh</code>。想抓个包、看个端口，总不能往运行中的容器里装东西。<code>nsenter</code> 是这类场景的救星：<strong>从宿主机直接进入容器的命名空间执行命令</strong>，容器里缺工具也没关系——用的是宿主机的。</p>
<!-- -->
<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>
<p>容器隔离的本质是 Linux namespace。<code>nsenter</code> 是对 <code>setns</code> 系统调用的封装：指定一个目标进程的 PID，把当前命令「塞进」它的某个命名空间里执行。容器里 1 号进程的所有命名空间就是这个容器的隔离边界，进去就等于站在容器内部。</p>
<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>
<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>
<p>常用命名空间选项：</p>
<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>
<p>也可以不通过 PID、直接指定命名空间文件，比如 Kubernetes 注册的：<code>nsenter --net=/var/run/netns/cni-xxx ...</code></p>
<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>
<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>
<p>K8s 里一个 Pod 的所有容器共享网络命名空间，所以<strong>进 pause 沙箱的网络空间就等于进了整个 Pod 的网络</strong>。</p>
<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>
<p><strong>抓容器网卡的包</strong>（最经典，配合 <a class="" href="https://cooree.co/blog/tcpdump-practical-notes">tcpdump 笔记</a>一起看）：</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 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>
<p><strong>看容器里实际监听的端口</strong>（镜像里没 <code>ss</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 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>
<p><strong>看容器视角的挂载和磁盘</strong>：</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 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>
<p><strong>验证容器内 DNS 解析</strong>：</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 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>
<p><strong>完全进入容器环境执行一系列命令</strong>（近似 <code>docker exec</code>，但不要求容器里有 shell）：</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 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>
<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>
<ul>
<li class=""><strong>需要 root 或 <code>CAP_SYS_ADMIN</code></strong>，普通用户直接跑会 permission denied</li>
<li class=""><strong>目标进程退出，命名空间就没了</strong>：拿着 PID 正准备进，容器恰好重启，PID 失效，报 <code>setns: cannot set namespace</code>——重新取一次 PID 即可</li>
<li class=""><strong><code>-m</code> 里别乱动</strong>：在挂载命名空间里 umount 或挂东西影响的是容器本体，只读看看就好</li>
<li class="">进网络命名空间后看到的 <code>eth0</code> 是<strong>容器的网卡</strong>，和宿主机的 <code>eth0</code> 不是一回事，别抓错方向</li>
</ul>
<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>
<p>nsenter 把「容器里没工具」这个借口彻底消灭了：宿主机的 tcpdump、ss、ip、nslookup 全都是容器的排查工具。记住核心三板斧——<code>docker inspect</code> 拿 PID、<code>nsenter -t $PID -n</code> 进网络空间、完事退出不留痕。它比进容器装调试镜像优雅得多，也不会污染运行环境。</p>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="Docker" term="Docker"/>
        <category label="Kubernetes" term="Kubernetes"/>
        <category label="排查" term="排查"/>
        <category label="nsenter" term="nsenter"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[nvm：Node 版本管理与国内安装加速]]></title>
        <id>https://cooree.co/blog/nvm-install-and-mirror</id>
        <link href="https://cooree.co/blog/nvm-install-and-mirror"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[nvm 的安装方式、国内网络下的加速配置和日常命令，以及几个容易踩的坑。]]></summary>
        <content type="html"><![CDATA[<p>前端项目的 Node 版本要求五花八门：老项目锁 Node 16，新项目要 Node 20+，CI 镜像又是另一个版本。系统包管理器装的 Node 只有一个版本，来回卸载重装不现实。nvm 就是干这个的：把多个 Node 版本装进用户目录，一条命令切换。</p>
<!-- -->
<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>
<p>官方安装脚本（版本号以 <a href="https://github.com/nvm-sh/nvm/releases" target="_blank" rel="noopener noreferrer" class="">nvm  releases 页</a>为准，写这篇时最新是 v0.40.8）：</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 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>
<p>脚本做的事很简单：把 nvm 克隆到 <code>~/.nvm</code>，然后往你的 <code>~/.bashrc</code> / <code>~/.zshrc</code> 里追加几行初始化代码。装完<strong>重开终端</strong>或手动生效：</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 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>
<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>
<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>
<p>nvm 装好了，装 Node 还要从 nodejs.org 下载，同样慢。把下载源换成 npmmirror：</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%)"># 写入 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>
<p>之后再装版本就丝滑了：</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 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>
<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>
<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>
<p>项目里放一个 <code>.nvmrc</code> 文件（内容就一行版本号，如 <code>20</code>），进目录后 <code>nvm use</code> 不带参数会自动读它，团队协作时每人手上的版本就统一了。</p>
<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>
<ul>
<li class=""><strong>新开终端 nvm 失效</strong>：初始化代码没写进你实际用的 shell 的 rc 文件（bash 和 zsh 是两份）。用 <code>echo $SHELL</code> 确认自己跑的是什么 shell</li>
<li class=""><strong><code>sudo</code> 下 nvm 不存在</strong>：nvm 装在用户目录，root 的环境里没有它。需要全局场景就换思路，别 sudo</li>
<li class=""><strong>全局 npm 包不共享</strong>：每个 Node 版本有自己独立的全局包目录，切版本后 <code>npm i -g</code> 装过的工具要重装。装完新版本可以用 <code>nvm install 20 --reinstall-packages-from=16</code> 一次性搬过去</li>
<li class=""><strong>别用 brew 装 nvm</strong>：官方明确不支持，brew 版和初始化脚本经常闹别扭，老老实实走官方脚本</li>
</ul>
<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>
<p>nvm 本身没什么技术含量，但它是前端环境的第一块地基：装对一次，后面所有项目的版本切换都是一句话的事。国内使用记住两个加速点——安装脚本走代理或镜像，装 Node 前把 <code>NVM_NODEJS_ORG_MIRROR</code> 指到 npmmirror。</p>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="Node.js" term="Node.js"/>
        <category label="工具" term="工具"/>
        <category label="nvm" term="nvm"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[tcpdump 实战笔记：从抓包参数到排查菜谱]]></title>
        <id>https://cooree.co/blog/tcpdump-practical-notes</id>
        <link href="https://cooree.co/blog/tcpdump-practical-notes"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[tcpdump 的常用参数、过滤表达式和几个拿来即用的排查菜谱，以及和 nsenter 配合抓容器包的方法。]]></summary>
        <content type="html"><![CDATA[<p>网络问题排查到最后，十有八九要落到「抓个包看看」。tcpdump 是Linux 上抓包的第一工具，参数和表达式看着多，常用的就那一小撮。这篇是我的随手笔记，按「参数 → 表达式 → 菜谱」组织，用的时候直接抄。</p>
<!-- -->
<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>
<p>大多数发行版自带，没有就 <code>apt install tcpdump</code> / <code>yum install tcpdump</code>。抓包需要 root 或 <code>CAP_NET_RAW</code> 能力。</p>
<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>
<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>
<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>
<p>组合规则：<code>and</code>、<code>or</code>、<code>not</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 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>
<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>
<p><strong>「服务通不通」先看握手</strong>——只有 SYN 没有 ACK，多半是对面没监听或中间被丢：</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 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>
<p><strong>抓 HTTP 请求明文看内容</strong>：</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 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>
<p><strong>看 DNS 解析走向</strong>（K8s 里排查 CoreDNS 特别好用）：</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 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>
<p><strong>「小包通、大包卡死」——MTU 黑洞排查</strong>：症状很典型——能 ping 通、能建连、小响应正常，一传大文件就卡死，跨隧道（WireGuard / IPsec / VXLAN）链路最常见。隧道把 MTU 吃小了，而路径上的 ICMP「需要分片」通知又被防火墙吞了，大包发出去就石沉大海。</p>
<p>先在发大文件的一侧看大包是不是在反复重传：</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 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>
<p>再到隧道接口上看有没有人提醒我们降包长：</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 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>
<p>确认后给 TCP 连接钳制 MSS，让包长不越线即可解决：</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 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>
<p><strong>写文件回去用 Wireshark 细读</strong>：</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 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>
<p><strong>抓容器网卡的包</strong>：容器里没 tcpdump，从宿主机借——先 <code>docker inspect</code> 拿 PID 再 <a class="" href="https://cooree.co/blog/nsenter-container-debug">nsenter</a> 进网络空间：</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 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>
<p><strong>长期值守抓偶发问题</strong>（滚动文件 + 限量）：</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 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>
<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>
<ul>
<li class=""><strong>先看 dropped 计数</strong>：结束时 tcpdump 会打印 <code>dropped by kernel</code> 数量，不为 0 说明抓的速率赶不上流量，加过滤表达式收窄或换 <code>-s</code> 减小快照长度</li>
<li class=""><strong>抓的位置决定看到什么</strong>：容器场景在宿主机 <code>cni0</code>、<code>veth</code> 对、物理网卡上抓到的视角都不一样；跨节点流量在物理网卡上是封装后的包（flannel 是 UDP 4789），想看成色要选对位置</li>
<li class=""><strong><code>-A</code> 对 TLS 没用</strong>：443 上的内容全是密文，别浪费时间，最多看看 ClientHello 里的 SNI</li>
<li class=""><strong>生产环境先估量</strong>：高流量网卡上裸跑 <code>tcpdump -i any</code> 等于自杀，永远先加过滤条件和 <code>-c</code> 限量</li>
</ul>
<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>
<p>tcpdump 的心法就两条：一是<strong>用表达式把范围缩到最小</strong>，问题流量的特征越具体越好；二是<strong>拿不准就 <code>-w</code> 落盘</strong>，丢给 Wireshark 慢慢看比盯着滚屏强。再配合 nsenter 进容器网络空间，容器网络问题也基本通吃。</p>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="Linux" term="Linux"/>
        <category label="网络" term="网络"/>
        <category label="排查" term="排查"/>
        <category label="tcpdump" term="tcpdump"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[watchtower：让容器自动跟上镜像更新]]></title>
        <id>https://cooree.co/blog/watchtower-auto-update</id>
        <link href="https://cooree.co/blog/watchtower-auto-update"/>
        <updated>2026-10-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[watchtower 通过轮询镜像仓库自动更新运行中的容器。记录它的部署方式、常用配置、通知渠道和 HTTP API 触发模式，并与 autodok 做选型对比。]]></summary>
        <content type="html"><![CDATA[<p>上篇写的 <a class="" href="https://cooree.co/blog/autodok-cicd-container-update">autodok</a> 是「按需触发」派：CI 构建完镜像后 POST 一下，它才去更新容器。这篇写它的对立面——<strong>轮询派</strong>的代表 watchtower：自己定时去问镜像仓库「有没有新镜像」，有就拉下来原地重启容器，全程不需要 CI 参与。</p>
<p>两种方式没有优劣，只有适不适合，文末给出选型对比。</p>
<!-- -->
<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>
<ul>
<li class="">GitHub：<a href="https://github.com/containrrr/watchtower" target="_blank" rel="noopener noreferrer" class="">containrrr/watchtower</a>（Go 编写，Apache-2.0 协议）</li>
<li class="">官方文档：<a href="https://containrrr.dev/watchtower/" target="_blank" rel="noopener noreferrer" class="">containrrr.dev/watchtower</a></li>
<li class="">Docker Hub：<a href="https://hub.docker.com/r/containrrr/watchtower" target="_blank" rel="noopener noreferrer" class="">containrrr/watchtower</a></li>
</ul>
<p>工作原理一句话：watchtower 挂载 <code>docker.sock</code>，按设定的周期拿着运行中容器的镜像去仓库比对 digest，发现新镜像就拉取，然后<strong>用原来的启动配置</strong>（卷、端口、环境变量）重建容器。</p>
<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>
<p>最简一行跑起来：</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 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>
<p>实际使用推荐 compose，把常用参数写清楚：</p>
<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>
<p><code>--cleanup</code> 让更新后顺手删掉旧镜像，避免磁盘被旧镜像悄悄吃满；<code>--interval 3600</code> 把默认 24 小时的轮询周期改成 1 小时。</p>
<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>
<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>
<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>
<p>默认管理所有容器，生产上一般要收窄范围。两种姿势：</p>
<p><strong>命令行点名</strong>：直接在命令末尾写容器名，只管理列出的：</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 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>
<p><strong>标签过滤</strong>（推荐，配合 <code>--label-enable</code>）：只动显式打标的容器，新增容器默认不受管，最安全：</p>
<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>
<p>反过来，给容器打 <code>com.centurylinklabs.watchtower.enable=false</code> 可以明确排除。</p>
<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>
<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>
<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>
<p>配合 <code>--notification-title-tag</code> 加标题前缀，多台机器跑多个 watchtower 时能分清通知来自哪台。</p>
<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>
<p>很多人不知道 watchtower 也有按需触发的一面。开启 HTTP API 模式后，它暴露 <code>POST /v1/update</code> 端点，外部（比如 CI 流水线）可以主动触发更新：</p>
<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>
<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>
<p>注意：<strong>开了 API 模式后默认关闭周期轮询</strong>，想两者并存要加 <code>--http-api-periodic-polls</code>。这个设计思路和 autodok 一致——把触发权交还给流水线。</p>
<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>
<p>拉私有仓库的镜像需要凭据，两种方式：</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%)"># 方式一：环境变量</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>
<p>方式二有个坑：bind mount 绑定的是 inode，<code>docker login</code> 或编辑器保存文件时是「新建再替换」，inode 变了，容器里的凭据就停留在旧版本。<strong>解决办法是挂软链接</strong>——先 <code>ln -s ~/.docker/config.json ~/docker-config.json</code>，再挂载软链接，inode 就稳定了。</p>
<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>
<ul>
<li class=""><strong>生产慎用全自动</strong>：数据库、有状态服务不要交给 watchtower 自动更新，镜像一换数据面就重建，滚动更新和备份策略都不是它的职责。这类服务打 <code>enable=false</code> 排除掉</li>
<li class=""><strong>先 monitor-only 观察</strong>：上线初用 <code>--monitor-only</code> + 通知跑一两周，确认更新频率和对象符合预期再开自动更新</li>
<li class=""><strong>cleanup 是把双刃剑</strong>：删旧镜像省磁盘，但出问题时少了「秒回滚旧镜像」这条路。重要服务可以不开 cleanup，改靠定期 <code>docker image prune</code></li>
<li class=""><strong>生命周期钩子</strong>：需要在更新前执行备份/排空流量等操作，可以看官方文档的 lifecycle hooks，给容器配 <code>pre-update</code>/<code>post-update</code> 命令</li>
</ul>
<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>
<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>
<p>两者不互斥：我自己的用法是<strong>生产用 autodok 跟着流水线走，个人小服务用 watchtower 开着 label 过滤自动跟进</strong>。</p>
<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>
<p>watchtower 的价值在于「零接入成本」：挂个 socket、起个容器，存量服务立刻获得自动更新能力。代价是更新时机的控制权不在你手里。用 label 过滤收窄管理范围、配上通知渠道、重要服务坚决排除，它就是一个省心的守夜人。</p>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="Docker" term="Docker"/>
        <category label="自动化运维" term="自动化运维"/>
        <category label="watchtower" term="watchtower"/>
        <category label="CI/CD" term="CI/CD"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[博客编写示例：从元信息到运维记录]]></title>
        <id>https://cooree.co/blog/blog-writing-example</id>
        <link href="https://cooree.co/blog/blog-writing-example"/>
        <updated>2026-10-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[本站博客写作模板，说明文章元信息、摘要截断、代码块、图片和提示框的用法。]]></summary>
        <content type="html"><![CDATA[<p>这是一篇可复制的博客写作示例。博客适合记录运维实践、故障复盘和学习心得；系统化的技术手册可以放在 docs 目录中。</p>
<!-- -->
<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>
<p>文章放在项目根目录的 <code>blog/</code> 下，也可以按主题建立子目录，例如 <code>blog/containers/docker-inspection.md</code>。使用 <code>.md</code> 或 <code>.mdx</code> 文件，开头写 YAML 元信息，后面写 Markdown 正文。</p>
<p>目录用于整理源文件，不会自动成为 Navbar 分类。本文设置了 <code>slug: blog-writing-example</code>，对应地址是 <code>/blog/blog-writing-example</code>。复制本文件后，请修改标题、日期、摘要和 slug，避免地址重复。</p>
<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>
<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>
<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>
<p>这些字段不要求全部填写。本站建议显式填写上面示例中的字段，避免依赖文件名推断标题或日期。YAML 使用空格缩进；包含特殊字符的标题或描述可用引号包裹。</p>
<p><code>authors.yml</code> 目前使用“容器运维工程师”作为显示名称，可以自行改成昵称，并按需添加个人主页或头像。</p>
<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>
<p>博客插件沿用 Docusaurus 的文章处理，在此基础上按 <code>sticky</code> 值降序排列，并将前 10 篇文章提供给首页。需要置顶时，可在元信息中添加 <code>sticky: 1</code>；日常文章可以省略。<code>date</code> 用于发布时间和默认时间排序。</p>
<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>
<p>在开头写一至两段摘要，再插入以下标记。标记前的内容用于博客列表摘要，完整正文仍会显示：</p>
<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>
<p><code>description</code> 与列表摘要不是同一个用途，建议同时填写描述和截断标记。</p>
<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>
<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>
<p>记录操作原因、预期结果、适用版本和环境。示例目标是查看 Docker 容器的运行状态，不代表已经对实际环境执行操作。</p>
<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>
<ul>
<li class="">环境：填写测试或生产环境。</li>
<li class="">版本：填写 Docker 和操作系统版本。</li>
<li class="">权限：确认具备访问目标 Docker 服务的权限。</li>
<li class="">变更窗口：涉及变更时填写时间和影响范围。</li>
</ul>
<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>
<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>
<p>在命令后记录预期输出、实际结果和异常判断依据。日志中如有密码、令牌或内部地址，发布前先处理敏感信息。</p>
<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>
<ul>
<li class="">验证：记录服务状态、监控指标和业务检查结果。</li>
<li class="">回滚：若涉及配置变更，写明恢复步骤和验证方法。</li>
<li class="">本例仅展示查询命令，无需回滚；实际操作请按影响填写。</li>
</ul>
<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>
<p>采用 Docusaurus 标准语法，类型后可用方括号设置标题，正文与冒号标记之间保留空行：</p>
<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>
<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>
<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>
<p>常用类型包括 <code>note</code>、<code>tip</code>、<code>info</code>、<code>warning</code>、<code>danger</code>。</p>
<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>
<p>本地图片放在 <code>static/</code> 下，引用时省略 <code>static</code>。下面是语法示例，需要先放入实际图片再使用：</p>
<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>
<p>Markdown 可以直接写链接、表格、列表和代码块；如需使用 React 组件，再考虑 MDX 和对应的组件导入。</p>
<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>
<ul>
<li class="">修改 <code>slug</code>、<code>title</code>、<code>date</code>、<code>description</code> 和标签。</li>
<li class="">确认 <code>authors</code> 能在作者配置中找到。</li>
<li class="">保留一处摘要截断标记，检查正文和图片链接。</li>
<li class="">删除示例说明、占位内容和敏感信息。</li>
<li class="">运行 <code>pnpm dev</code> 查看文章与博客列表。</li>
<li class="">结束开发服务后运行 <code>pnpm build</code>，检查构建结果。</li>
</ul>]]></content>
        <author>
            <name>容器运维工程师</name>
        </author>
        <category label="运维" term="运维"/>
        <category label="写作指南" term="写作指南"/>
    </entry>
</feed>