<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>容器化部署 on 扎塔-Zata</title><link>https://www.zata.cc/tags/%E5%AE%B9%E5%99%A8%E5%8C%96%E9%83%A8%E7%BD%B2/</link><description>Recent content in 容器化部署 on 扎塔-Zata</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>扎塔-Zata</copyright><lastBuildDate>Thu, 24 Sep 2026 17:09:06 +0800</lastBuildDate><atom:link href="https://www.zata.cc/tags/%E5%AE%B9%E5%99%A8%E5%8C%96%E9%83%A8%E7%BD%B2/index.xml" rel="self" type="application/rss+xml"/><item><title>CICD</title><link>https://www.zata.cc/p/cicd/</link><pubDate>Wed, 25 Feb 2026 09:52:08 +0800</pubDate><guid>https://www.zata.cc/p/cicd/</guid><description>&lt;img src="https://www.zata.cc/p/cicd/images/index/index.png" alt="Featured image of post CICD" />&lt;h1 id="cicd-详细使用教程">CI/CD 详细使用教程
&lt;/h1>&lt;p>CI/CD 是现代软件开发中至关重要的实践，它代表持续集成（Continuous Integration）和持续部署（Continuous Deployment）或持续交付（Continuous Delivery）。本教程将 guiding 您了解 CI/CD 的核心概念、工作流程以及如何在实际项目中落地。&lt;/p>
&lt;p>&lt;strong>什么是持续集成（CI）&lt;/strong>&lt;/p>
&lt;p>持续集成是指开发人员频繁地将代码集成到共享仓库中。每次集成都会通过自动化的构建和测试来验证，以便尽早发现错误。核心目标是减少集成冲突，提高代码质量。&lt;/p>
&lt;p>&lt;strong>什么是持续部署与交付（CD）&lt;/strong>&lt;/p>
&lt;p>持续交付确保代码在经过测试后可以随时可靠地发布到生产环境。持续部署则更进一步，将通过所有测试的代码自动部署到生产环境，无需人工干预。这两者共同构成了自动化发布流水线。&lt;/p>
&lt;p>&lt;strong>CI/CD 的核心价值&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>提高效率&lt;/strong>：自动化重复任务，减少人工操作时间。&lt;/li>
&lt;li>&lt;strong>降低风险&lt;/strong>：小步快跑，每次变更范围小，出现问题容易回滚。&lt;/li>
&lt;li>&lt;strong>快速反馈&lt;/strong>：开发人员能迅速得知代码构建和测试的结果。&lt;/li>
&lt;li>&lt;strong>质量保证&lt;/strong>：强制通过测试才能进入下一阶段，确保交付质量。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>主流 CI/CD 工具介绍&lt;/strong>&lt;/p>
&lt;p>市面上有多种工具可供选择，您可以根据团队技术栈进行选择：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Jenkins&lt;/strong>：开源灵活，插件生态丰富，适合复杂定制需求。&lt;/li>
&lt;li>&lt;strong>GitLab CI&lt;/strong>：与 GitLab 代码仓库深度集成，配置简单，使用方便。&lt;/li>
&lt;li>&lt;strong>GitHub Actions&lt;/strong>：原生集成于 GitHub，适合开源项目及托管在 GitHub 上的私有项目。&lt;/li>
&lt;li>&lt;strong>CircleCI&lt;/strong>：云端服务，配置简洁，支持多种语言环境。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>基础工作流程搭建&lt;/strong>&lt;/p>
&lt;p>一个标准的 CI/CD 流水线通常包含以下几个阶段：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>代码提交&lt;/strong>：开发人员将代码推送到版本控制系统（如 Git）。&lt;/li>
&lt;li>&lt;strong>触发构建&lt;/strong>：代码推送动作触发 CI 服务器开始工作。&lt;/li>
&lt;li>&lt;strong>依赖安装&lt;/strong>：系统自动安装项目所需的依赖包。&lt;/li>
&lt;li>&lt;strong>代码编译&lt;/strong>：将源代码编译为可执行文件或 artifacts。&lt;/li>
&lt;li>&lt;strong>自动化测试&lt;/strong>：运行单元测试、集成测试等验证代码逻辑。&lt;/li>
&lt;li>&lt;strong>代码扫描&lt;/strong>：进行静态代码分析，检查安全漏洞和规范。&lt;/li>
&lt;li>&lt;strong>构建镜像&lt;/strong>：如果是容器化部署，此处构建 Docker 镜像。&lt;/li>
&lt;li>&lt;strong>部署环境&lt;/strong>：将应用部署到测试环境或生产环境。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>简单配置示例&lt;/strong>&lt;/p>
&lt;p>以下是一个基于 GitHub Actions 的简单配置文件示例，展示了如何运行测试和构建：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CI Pipeline&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">push&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">main ]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Run tests&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">npm test&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Build project&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">npm run build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>最佳实践建议&lt;/strong>&lt;/p>
&lt;p>为了充分发挥 CI/CD 的优势，建议遵循以下原则：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>保持构建快速&lt;/strong>：优化测试和构建脚本，确保流水线能在几分钟内完成。&lt;/li>
&lt;li>&lt;strong>测试覆盖率高&lt;/strong>：确保自动化测试覆盖核心业务逻辑，避免漏测。&lt;/li>
&lt;li>&lt;strong>单一来源真理&lt;/strong>：所有配置代码化（Infrastructure as Code），存放在版本控制中。&lt;/li>
&lt;li>&lt;strong>失败即停止&lt;/strong>：一旦任何阶段失败，立即停止流水线并通知相关人员。&lt;/li>
&lt;li>&lt;strong>定期维护&lt;/strong>：定期更新工具和依赖，修复已知漏洞。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>常见问题与排查&lt;/strong>&lt;/p>
&lt;p>在使用初期，您可能会遇到构建失败或部署超时的问题。首先检查日志输出，定位错误阶段。如果是环境依赖问题，尝试清理缓存或重新安装依赖。如果是网络问题，检查服务器连通性及权限配置。保持日志清晰可读有助于快速定位问题根源。&lt;/p>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;p>实施 CI/CD 是一个循序渐进的过程。建议从简单的自动化构建开始，逐步加入测试、扫描和部署环节。通过不断迭代优化流水线，团队将获得更高的交付速度和更稳定的产品质量。希望本教程能帮助您顺利开启自动化运维之旅。&lt;/p>
&lt;h1 id="使用与配置">使用与配置
&lt;/h1>&lt;h2 id="-技巧分享利用阿里云容器镜像服务解决-github-镜像国内下载慢的问题">🚀 技巧分享：利用阿里云容器镜像服务解决 GitHub 镜像国内下载慢的问题
&lt;/h2>&lt;p>在部署 Docker 项目时，我们常遇到一个尴尬的场景：通过 GitHub Actions 或其他方式将镜像推送到国外服务器（或 GitHub Packages）后，&lt;strong>国内服务器拉取镜像的速度非常慢，甚至超时&lt;/strong>。但受限于网络策略，GitHub 往往无法直接将镜像推送到国内的镜像源。&lt;/p>
&lt;p>&lt;strong>💡 解决方案：使用阿里云容器镜像服务（ACR）作为“中转站”&lt;/strong>&lt;/p>
&lt;p>我们可以利用阿里云提供的容器镜像服务，搭建一个国内的镜像仓库。流程如下：
&lt;code>GitHub/国外服务器&lt;/code> &amp;ndash;&amp;gt; &lt;code>阿里云镜像仓库&lt;/code> &amp;ndash;&amp;gt; &lt;code>国内服务器&lt;/code>&lt;/p>
&lt;p>&lt;strong>🛠️ 操作实录&lt;/strong>&lt;/p>
&lt;p>如截图所示，登录阿里云控制台后，操作非常直观：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>开通实例&lt;/strong>：选择**“个人版实例”**（对于个人开发者或小团队，免费额度通常足够使用）。&lt;/li>
&lt;li>&lt;strong>创建仓库&lt;/strong>：点击**“创建镜像仓库”**，设置好命名空间。
&lt;ul>
&lt;li>&lt;em>建议将仓库类型设置为&lt;/em>*“私有”**，以保障代码和镜像安全。*&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>配置同步&lt;/strong>：
&lt;ul>
&lt;li>在 CI/CD 流程（如 GitHub Actions）中，增加一步推送动作，将构建好的镜像同时 &lt;code>docker push&lt;/code> 到阿里云的仓库地址。&lt;/li>
&lt;li>或者在阿里云后台配置“实例同步”功能，自动从 GitHub/Docker Hub 同步镜像。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>✅ 最终效果&lt;/strong>&lt;/p>
&lt;p>配置完成后，国内服务器只需修改 &lt;code>docker pull&lt;/code> 的地址为阿里云的仓库地址（例如 &lt;code>registry.cn-hangzhou.aliyuncs.com/...&lt;/code>），即可享受&lt;strong>国内专线速度&lt;/strong>，彻底告别下载卡顿。&lt;/p>
&lt;h2 id="告别手动复制粘贴我们如何实现-windows-环境下的全自动化部署">告别手动复制粘贴：我们如何实现 Windows 环境下的全自动化部署
&lt;/h2>&lt;blockquote>
&lt;p>&lt;strong>摘要：&lt;/strong> 每次发布新版本都要手动停止服务、复制文件、重启程序？在这篇文章中，我们将分享如何利用 GitHub Actions 和自托管 Runner (Self-hosted Runner) 构建一条流畅的 Windows 到 Windows CI/CD 流水线，彻底告别繁琐的手动部署。&lt;/p>
&lt;/blockquote>
&lt;p>&lt;strong>1. 曾经的痛点：手动部署的“黑暗时代”&lt;/strong>&lt;/p>
&lt;p>在过去的开发周期中，每次要在测试机或生产机上更新我们的 Windows 桌面软件（或后台服务），流程大概是这样的：&lt;/p>
&lt;ol>
&lt;li>在开发机上编译打包。&lt;/li>
&lt;li>将几十 MB 甚至上百 MB 的安装包或压缩包通过微信、网盘或共享文件夹传到目标机器。&lt;/li>
&lt;li>远程登录目标机器。&lt;/li>
&lt;li>手动打开任务管理器，杀掉旧版本的进程。&lt;/li>
&lt;li>解压新文件，覆盖旧文件。&lt;/li>
&lt;li>重新启动程序，祈祷一切正常运行。&lt;/li>
&lt;/ol>
&lt;p>这不仅耗时耗力，而且极其容易出错（比如漏掉配置文件、忘记关闭旧进程导致文件被占用）。随着迭代速度的加快，这种“刀耕火种”的部署方式已经成为了团队效率的最大瓶颈。&lt;/p>
&lt;p>&lt;strong>2. 破局思路：引入 CI/CD 与自托管 Runner&lt;/strong>&lt;/p>
&lt;p>为了解决这个问题，我们决定引入自动化流水线。考虑到我们的开发环境和目标环境都是 Windows，并且代码托管在支持 CI/CD 的平台上，我们最终敲定了 &lt;strong>“云端触发 + 本地自托管 Runner 执行”&lt;/strong> 的架构。&lt;/p>
&lt;p>核心思路很简单：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>开发端：&lt;/strong> 开发者只需专注于写代码，完成后执行 &lt;code>git push&lt;/code>。&lt;/li>
&lt;li>&lt;strong>云端桥梁：&lt;/strong> 代码仓库监听到提交后，生成部署指令，下发给目标机器。&lt;/li>
&lt;li>&lt;strong>目标端：&lt;/strong> 目标机器上安装了一个后台服务（Runner），它接收指令后，自动在本地拉取代码、编译、替换文件并重启应用。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. 核心实践：部署流水线的关键步骤&lt;/strong>&lt;/p>
&lt;p>我们在目标 Windows 机器上配置了 Actions Runner，并将其注册为 Windows 服务以保证常驻运行。接下来，我们编写了流水线脚本，主要包含以下几个关键自动化步骤：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>自动化清理与准备：&lt;/strong> 脚本首先会静默停止正在运行的旧版本进程 &lt;code>Stop-Process -Name &amp;quot;MyApp&amp;quot; -ErrorAction SilentlyContinue&lt;/code>，确保文件解除占用。&lt;/li>
&lt;li>&lt;strong>自动化构建：&lt;/strong> Runner 直接在目标机器上拉取最新 &lt;code>main&lt;/code> 分支的代码，并执行编译命令，生成最新的二进制文件。&lt;/li>
&lt;li>&lt;strong>自动化覆盖：&lt;/strong> 使用 PowerShell 脚本将编译好的产物精准复制并覆盖到软件的实际运行目录中。&lt;/li>
&lt;li>&lt;strong>自动化启动：&lt;/strong> 最后，脚本拉起新版本的可执行文件，整个过程在几秒钟内无缝完成。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>4. 取得的收益&lt;/strong>&lt;/p>
&lt;p>这条简单的 CI/CD 流水线落地后，给我们带来了肉眼可见的改变：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>🚀 效率飙升：&lt;/strong> 部署时间从过去的 10 分钟缩短到了 1 分钟以内，彻底解放了开发人员的双手。&lt;/li>
&lt;li>&lt;strong>🛡️ 零人为失误：&lt;/strong> 标准化的脚本代替了人工操作，再也没有出现过“忘了覆盖某个动态链接库”这种低级错误。&lt;/li>
&lt;li>&lt;strong>🔄 快速迭代：&lt;/strong> 真正实现了“代码一推，新版就绪”，团队可以更专注于业务逻辑的开发，而不是被运维琐事牵绊。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>5. 结语&lt;/strong>&lt;/p>
&lt;p>虽然 Windows 环境下的持续集成/持续部署在配置上可能比纯 Linux 环境稍显繁琐，但通过合理利用自托管 Runner，我们依然可以获得极致的自动化体验。如果你的团队也正在忍受手动部署的折磨，不妨花半天时间把这套流程搭建起来，这绝对是一笔稳赚不赔投资！&lt;/p></description></item><item><title>Dokploy</title><link>https://www.zata.cc/p/dokploy/</link><pubDate>Sun, 22 Feb 2026 15:43:30 +0800</pubDate><guid>https://www.zata.cc/p/dokploy/</guid><description>&lt;img src="https://www.zata.cc/p/dokploy/images/index/index.png" alt="Featured image of post Dokploy" />&lt;h1 id="快速安装使用教程-注意如果内存小于等于2g一定要加虚拟内存否则会卡死">快速安装使用教程 (注意，如果内存小于等于2G，一定要加虚拟内存，否则会卡死)
&lt;/h1>&lt;p>&lt;a class="link" href="https://dokploy.com/" target="_blank" rel="noopener"
>官网地址&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://docs.dokploy.com/docs/core/manual-installation" target="_blank" rel="noopener"
>关于swarm的安装&lt;/a>&lt;/p>
&lt;p>注意: 如果内存很小的机器,安装之后千万别点升级dokploy的按钮, 即使你开了Swap也没用,只要一升级,很大概率就会很绝望了(dokploy服务崩溃且无法恢复),内存1G的推荐安装0.26.6版本,其他版本可能就爆内存了 export DOKPLOY_VERSION=v0.26.6 &amp;amp;&amp;amp; curl -sSL &lt;a class="link" href="https://dokploy.com/install.sh" target="_blank" rel="noopener"
>https://dokploy.com/install.sh&lt;/a> | sh &amp;mdash; 20260310&lt;/p>
&lt;p>一键安装脚本，安装完成之后会给一个地址&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">ADVERTISE_ADDR&lt;/span>&lt;span class="o">=&lt;/span>&amp;lt;指定IP地址&amp;gt; &lt;span class="c1"># 需要指定公网IP&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://dokploy.com/install.sh &lt;span class="p">|&lt;/span> sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 或者&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://dokploy.com/install.sh &lt;span class="p">|&lt;/span> &lt;span class="nv">ADVERTISE_ADDR&lt;/span>&lt;span class="o">=&lt;/span>&amp;lt;你的服务器公网IP&amp;gt; bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>帮助子节点安装docker&lt;/p>
&lt;p>&lt;strong>阿里云服务器&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Add the Aliyun Repository&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;deb [arch=&lt;/span>&lt;span class="k">$(&lt;/span>dpkg --print-architecture&lt;span class="k">)&lt;/span>&lt;span class="s2">] https://mirrors.aliyun.com/docker-ce/linux/ubuntu &lt;/span>&lt;span class="k">$(&lt;/span>lsb_release -cs&lt;span class="k">)&lt;/span>&lt;span class="s2"> stable&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Update your Package List&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Install Docker &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># verify the installation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">#配置镜像加速&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo tee /etc/docker/daemon.json &lt;span class="s">&amp;lt;&amp;lt;-&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> &amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://&amp;lt;你的加速镜像地址，进入阿里云镜像加速服务获取&amp;gt;.mirror.aliyuncs.com&amp;#34;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl restart docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> containerd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>腾讯云服务器&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo install -m &lt;span class="m">0755&lt;/span> -d /etc/apt/keyrings
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -fsSL http://mirrors.tencentyun.com/docker-ce/linux/ubuntu/gpg &lt;span class="p">|&lt;/span> sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo chmod a+r /etc/apt/keyrings/docker.gpg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;deb [arch=&lt;/span>&lt;span class="k">$(&lt;/span>dpkg --print-architecture&lt;span class="k">)&lt;/span>&lt;span class="s2"> signed-by=/etc/apt/keyrings/docker.gpg] http://mirrors.tencentyun.com/docker-ce/linux/ubuntu \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &lt;/span>&lt;span class="k">$(&lt;/span>. /etc/os-release &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$VERSION_CODENAME&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2"> stable&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo tee /etc/docker/daemon.json &lt;span class="s">&amp;lt;&amp;lt;-&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> &amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://mirror.ccs.tencentyun.com&amp;#34;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl restart docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> containerd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -fsSL https://get.docker.com &lt;span class="p">|&lt;/span> sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 设置开机自启 &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">systemctl &lt;span class="nb">enable&lt;/span> --now docker
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 作为子节点加入到 swarm 集群&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker swarm join &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --token &amp;lt;TOKEN&amp;gt; &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --advertise-addr &amp;lt;当前子节点的_公网IP&amp;gt; &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --data-path-addr &amp;lt;当前子节点的_公网IP&amp;gt; &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &amp;lt;Manager_公网IP&amp;gt;:2377
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 检查是否成功加入 swarm 集群&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">telnet &amp;lt;Manager_公网IP&amp;gt; &lt;span class="m">2377&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">telnet &amp;lt;Manager_公网IP&amp;gt; &lt;span class="m">7946&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>查看所有容器的运行状态&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker service ps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="服务器爬墙来安装">服务器爬墙来安装
&lt;/h2>&lt;p>服务器爬墙的内容可以看我另一篇 《服务器爬墙》教程&lt;/p>
&lt;p>&lt;strong>🛠️ Dokploy 完美安装四部曲&lt;/strong>&lt;/p>
&lt;p>&lt;strong>第一步：基础环境准备 (Ubuntu/Debian)&lt;/strong>
首先确保系统干净，并安装必要的工具。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">apt update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt upgrade -y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">apt install -y curl vim net-tools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>第二步：安装并优化 Docker (核心环节)&lt;/strong>
不要直接运行 Dokploy 脚本，先手动把 Docker 装好并配置代理。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>安装 Docker&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -fsSL https://get.docker.com &lt;span class="p">|&lt;/span> bash
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">systemctl &lt;span class="nb">enable&lt;/span> --now docker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>配置 Docker 代理 (解决镜像下载失败)&lt;/strong>：
这是国内服务器成功的关键。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir -p /etc/systemd/system/docker.service.d
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">vim /etc/systemd/system/docker.service.d/http-proxy.conf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>写入以下内容（假设你的 Mihomo 代理在 7890）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[Service]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">Environment&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;HTTP_PROXY=http://127.0.0.1:7890&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">Environment&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;HTTPS_PROXY=http://127.0.0.1:7890&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">Environment&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;NO_PROXY=localhost,127.0.0.1,你的服务器公网IP&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>重启生效&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">systemctl restart docker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>第三步：部署 Dokploy&lt;/strong>
现在 Docker 已经可以丝滑地拉取镜像了，直接运行官方脚本：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 注意替换成你自己的服务器公网 IP&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://dokploy.com/install.sh &lt;span class="p">|&lt;/span> &lt;span class="nv">ADVERTISE_ADDR&lt;/span>&lt;span class="o">=&lt;/span>你的服务器公网IP bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>这一步脚本会自动完成以下操作：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>初始化 Docker Swarm（容器集群模式）。&lt;/li>
&lt;li>创建 &lt;code>dokploy-network&lt;/code> 虚拟网络。&lt;/li>
&lt;li>生成随机的数据库密码并存入 &lt;code>Docker Secrets&lt;/code>。&lt;/li>
&lt;li>部署 &lt;code>Postgres&lt;/code> (数据库)、&lt;code>Redis&lt;/code> (缓存) 和 &lt;code>Dokploy&lt;/code> (主程序)。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>第四步：防火墙与初始化&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>放行端口&lt;/strong>：
去你的云商后台（腾讯云/阿里云等）开启以下入站规则：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>3000&lt;/strong>：Dokploy 面板访问端口。&lt;/li>
&lt;li>&lt;strong>80 / 443&lt;/strong>：未来你部署应用后的访问端口。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>访问面板&lt;/strong>：
打开浏览器：&lt;code>http://你的服务器IP:3000&lt;/code>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>第一次进入&lt;/strong>：会要求你创建管理员账号（邮箱/密码）。&lt;/li>
&lt;li>&lt;strong>配置面板&lt;/strong>：进入后在 &lt;code>Settings&lt;/code> 中确认 &lt;code>Server IP&lt;/code> 正确。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>💡 为什么之前会失败？（复盘总结）&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">错误阶段&lt;/th>
&lt;th style="text-align: left">根本原因&lt;/th>
&lt;th style="text-align: left">表现&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>安装 Docker 报错&lt;/strong>&lt;/td>
&lt;td style="text-align: left">脚本传参语法不对&lt;/td>
&lt;td style="text-align: left">&lt;code>Failure writing output&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>创建容器一直 Preparing&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Docker 无法连接官方镜像仓库&lt;/td>
&lt;td style="text-align: left">镜像下载进度 0%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>PostgresError (密码错误)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">残留的旧数据库卷与新生成的密码冲突&lt;/td>
&lt;td style="text-align: left">容器一直重启，日志报 &lt;code>auth_failed&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="安装卡住时的清理方法">安装卡住时的清理方法
&lt;/h2>&lt;p>有时候安装Dokploy可能会卡住，需要清除重来，以下是完整的清理步骤：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 离开 swarm 并清理&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker swarm leave --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 删掉所有 Dokploy 相关的东西&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker service rm &lt;span class="k">$(&lt;/span>docker service ls -q&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker container rm -f &lt;span class="k">$(&lt;/span>docker ps -aq --filter &lt;span class="s2">&amp;#34;name=dokploy&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker volume rm &lt;span class="k">$(&lt;/span>docker volume ls -q --filter &lt;span class="s2">&amp;#34;name=dokploy&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker network rm &lt;span class="k">$(&lt;/span>docker network ls -q --filter &lt;span class="s2">&amp;#34;name=dokploy&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 更加彻底的：&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 删除所有服务&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker service rm &lt;span class="k">$(&lt;/span>docker service ls -q&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 删除 Dokploy 存储的密码密钥 (关键！)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker secret rm &lt;span class="k">$(&lt;/span>docker secret ls -q&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 删除网络&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker network rm dokploy-network
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 删除数据卷（如果你不介意清空重来，这能解决 99% 的数据库问题）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker volume rm &lt;span class="k">$(&lt;/span>docker volume ls -q&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 清理残留镜像（可选）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker system prune -a --volumes --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 再跑安装（加 --debug 看更详细输出）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://dokploy.com/install.sh &lt;span class="p">|&lt;/span> bash -s -- --debug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 或指定 advertise addr（如果你的公网IP不是自动检测到的）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://dokploy.com/install.sh &lt;span class="p">|&lt;/span> &lt;span class="nv">ADVERTISE_ADDR&lt;/span>&lt;span class="o">=&lt;/span>你的服务器公网IP bash
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="注意事项">注意事项
&lt;/h1>&lt;ol>
&lt;li>
&lt;p>只要改过了domin,就一定要重新deploy
&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-6.png"
width="644"
height="256"
srcset="https://www.zata.cc/p/dokploy/images/index/image-6_hu5312012935175865417.png 480w, https://www.zata.cc/p/dokploy/images/index/image-6_hu11201298481149940884.png 1024w"
loading="lazy"
alt="提醒重新部署"
class="gallery-image"
data-flex-grow="251"
data-flex-basis="603px"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>可以先用自己电脑ssh-copy-id 到远程服务器，然后把自己电脑上的ssh密钥复制过来
&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-1.png"
width="2754"
height="1642"
srcset="https://www.zata.cc/p/dokploy/images/index/image-1_hu12951991248830545399.png 480w, https://www.zata.cc/p/dokploy/images/index/image-1_hu8854949752212430651.png 1024w"
loading="lazy"
alt="可以复制自己电脑上的ssh密钥"
class="gallery-image"
data-flex-grow="167"
data-flex-basis="402px"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>子节点默认可能是没有docker的,需要安装一下
&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-2.png"
width="3404"
height="1932"
srcset="https://www.zata.cc/p/dokploy/images/index/image-2_hu10748364068089874623.png 480w, https://www.zata.cc/p/dokploy/images/index/image-2_hu6406890722659584139.png 1024w"
loading="lazy"
alt="没有docker报错"
class="gallery-image"
data-flex-grow="176"
data-flex-basis="422px"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>添加docker swarm 误操作添加了管理节点，然后又下线会导致原本的管理节点脑裂,详情需要看dokploy的官方文档
重新安装请查看前面的方法&lt;/p>
&lt;/li>
&lt;li>
&lt;p>dokploy很多时候部署失败可能是不提示的,尤其是使用 docker stack 的时候&lt;/p>
&lt;/li>
&lt;li>
&lt;p>配置了域名地址之后,有时候可能要等一会才能生效&lt;/p>
&lt;/li>
&lt;li>
&lt;p>网络配置
这一步非常重要，告诉 Docker 使用 Dokploy 已经建好的网络
networks:
dokploy-network:
external: true&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如何更换swarm的advertise addr
docker swarm init &amp;ndash;force-new-cluster &amp;ndash;advertise-addr &amp;lt;你的服务器IP&amp;gt;&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="一些应用的部署">一些应用的部署
&lt;/h1>&lt;h2 id="ip-重定向-解决切换ip后访问域名失败的问题-----20260323">IP 重定向 (解决切换IP后访问域名失败的问题) &amp;mdash; 20260323
&lt;/h2>&lt;p>将所有访问你的域名的请求重定向到你的新 IP 地址。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">version: &lt;span class="s1">&amp;#39;3.8&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">services:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip-redirector:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> image: nginx:alpine
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> restart: unless-stopped
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> networks:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - dokploy-network
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> labels:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - &lt;span class="s2">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 【修改这里 1】替换成你真实的域名&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - &lt;span class="s2">&amp;#34;traefik.http.routers.ip-redirector.rule=Host(`yourdomain.com`) || Host(`www.yourdomain.com`)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - &lt;span class="s2">&amp;#34;traefik.http.services.ip-redirector.loadbalancer.server.port=80&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - &lt;span class="s2">&amp;#34;traefik.http.routers.ip-redirector.entrypoints=websecure&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - &lt;span class="s2">&amp;#34;traefik.http.routers.ip-redirector.tls.certresolver=letsencrypt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> command: &amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> /bin/sh -c &lt;span class="s2">&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> echo &amp;#39;server {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> listen 80;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> location / {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> # 【修改这里 2】改成你的新IP！注意这里改成了 https://
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_pass https://1.2.3.4;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> # 传递真实访客信息
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header Host &lt;/span>&lt;span class="nv">$$&lt;/span>&lt;span class="s2">host;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header X-Real-IP &lt;/span>&lt;span class="nv">$$&lt;/span>&lt;span class="s2">remote_addr;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header X-Forwarded-For &lt;/span>&lt;span class="nv">$$&lt;/span>&lt;span class="s2">proxy_add_x_forwarded_for;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header X-Forwarded-Proto https;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> # 【新增：核心修复代码】开启 SNI，否则新服务器的 HTTPS 无法识别域名会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_ssl_server_name on;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_ssl_name &lt;/span>&lt;span class="nv">$$&lt;/span>&lt;span class="s2">host;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> # 支持 WebSocket 等长连接
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_http_version 1.1;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header Upgrade &lt;/span>&lt;span class="nv">$$&lt;/span>&lt;span class="s2">http_upgrade;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> proxy_set_header Connection \&amp;#34;upgrade\&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> }&amp;#39; &amp;gt; /etc/nginx/conf.d/default.conf &amp;amp;&amp;amp; nginx -g &amp;#39;daemon off;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">networks:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dokploy-network:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> external: &lt;span class="nb">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="docker-registry------20260307创建-未做测试">Docker Registry &amp;mdash; 20260307创建 未做测试
&lt;/h2>&lt;p>Docker Registry 原生并没有提供“自动根据时间删除镜像”的功能。要实现超过 7 天自动删除，必须分为两步完成：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>调用 API 删除标签&lt;/strong>：将超过 7 天的镜像标记为“已删除”（但此时物理磁盘空间还未释放）。&lt;/li>
&lt;li>&lt;strong>执行垃圾回收 (Garbage Collection)&lt;/strong>：清理那些失去标签的底层文件（Blob），真正释放磁盘空间。&lt;/li>
&lt;/ol>
&lt;p>为了在 Docker Compose 中实现自动化，我们可以&lt;strong>增加一个专门的清理服务（&lt;code>registry-cleanup&lt;/code>）&lt;/strong>。它会每天自动运行一个广受欢迎的开源 Python 脚本 &lt;code>registry-cli&lt;/code> 来删除旧镜像，并调用 Registry 的 GC 命令释放空间。&lt;/p>
&lt;p>下面是修改后的完整 &lt;code>docker-compose.yml&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.8&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># 定义数据卷，持久化存储镜像和认证信息&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">registry-data&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">registry-auth-data&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># 使用 Dokploy 预置的外部网络&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">dokploy-network&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">external&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 1. 认证辅助服务：生成账号 admin / 密码 123456&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">auto-setup-auth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">httpd:alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/bin/sh -c &amp;#34;htpasswd -Bbn admin 123456 &amp;gt; /auth/htpasswd&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">registry-auth-data:/auth&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 2. 核心 Registry 服务&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">registry&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">registry:2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">my-private-registry&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">always&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;5000:5000&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_AUTH&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">htpasswd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_AUTH_HTPASSWD_REALM&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Registry Realm&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_AUTH_HTPASSWD_PATH&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/auth/htpasswd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_X_FORWARDED_FOR&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_X_FORWARDED_PROTO&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">https&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 【关键配置】开启删除权限（必须开启，清理脚本才能工作）&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_STORAGE_DELETE_ENABLED&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_ACCESS_CONTROL_ALLOW_ORIGIN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;[https://registry-ui.zata.cafe]&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_ACCESS_CONTROL_ALLOW_METHODS&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;[HEAD,GET,OPTIONS,DELETE]&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_ACCESS_CONTROL_ALLOW_HEADERS&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;[Authorization,Accept,Cache-Control]&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">REGISTRY_HTTP_HEADERS_ACCESS_CONTROL_EXPOSE_HEADERS&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;[Docker-Content-Digest]&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">registry-data:/var/lib/registry&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">registry-auth-data:/auth&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">depends_on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">auto-setup-auth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">condition&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">service_completed_successfully&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry.rule=Host(`registry.zata.cafe`)&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry.entrypoints=websecure&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry.tls.certresolver=letsencrypt&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.services.registry.loadbalancer.server.port=5000&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=0&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 3. Web UI 管理界面&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">registry-ui&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">joxit/docker-registry-ui:latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">registry-ui&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">always&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">NGINX_PROXY_PASS_URL=http://my-private-registry:5000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">SINGLE_REGISTRY=true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">DELETE_IMAGES=true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">REGISTRY_TITLE=Zata Registry&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry-ui.rule=Host(`registry-ui.zata.cafe`)&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry-ui.entrypoints=websecure&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.registry-ui.tls.certresolver=letsencrypt&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.services.registry-ui.loadbalancer.server.port=80&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 4. 【新增】自动清理服务 (每天执行)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">registry-cleanup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">docker:cli&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">registry-cleanup&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">always&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 挂载宿主机的 Docker Socket，以便此容器能够向 registry 容器发送垃圾回收命令&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">/var/run/docker.sock:/var/run/docker.sock&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">depends_on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">registry&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">entrypoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;-c&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 核心自动化脚本&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 安装 Python 和 HTTP 请求库
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> apk add --no-cache python3 py3-requests curl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 下载著名的开源镜像清理脚本 registry-cli
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> curl -sSLO https://raw.githubusercontent.com/anoxis/registry-cli/master/registry.py
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> chmod +x registry.py&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;自动清理服务已启动...&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">while true; do&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;==== 开始调用 API 清理 7 天前的镜像标签 ====&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 参数说明:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># --keep-days 7 : 删除 7 天前的镜像&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># --keep-tags 1 : 即使超过 7 天，也强制保留最新生成的 1 个版本（防止仓库被彻底删空，如果你想彻底删空可去掉此参数）&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">python3 registry.py -r http://my-private-registry:5000 -l admin:123456 --delete --keep-days 7 --keep-tags 1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;==== 开始执行 GC (垃圾回收) 释放磁盘空间 ====&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 必须执行 --delete-untagged，否则上一段脚本删除的镜像文件依然会占用物理空间&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">docker exec my-private-registry registry garbage-collect --delete-untagged /etc/docker/registry/config.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;==== 清理与回收完成，休眠 24 小时 ====&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">sleep 86400&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">done&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>新增服务原理解析：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>基础镜像 (&lt;code>docker:cli&lt;/code>)&lt;/strong>：我们需要在脚本最后使用 &lt;code>docker exec&lt;/code> 去调用 Registry 容器执行垃圾回收，因此使用了带 docker 命令的基础镜像，并挂载了宿主机的 &lt;code>docker.sock&lt;/code>。&lt;/li>
&lt;li>&lt;strong>依赖安装&lt;/strong>：自动下载著名的 &lt;code>anoxis/registry-cli&lt;/code> 脚本，它擅长处理 Docker Registry 的 API，并且支持基于时间删除。&lt;/li>
&lt;li>&lt;strong>保留策略控制&lt;/strong>：
&lt;ul>
&lt;li>&lt;code>--keep-days 7&lt;/code>：这就是你要求的，超过 7 天的删除。&lt;/li>
&lt;li>&lt;code>--keep-tags 1&lt;/code>：（推荐设置）保护机制，如果某个镜像 1 个月没更新了，清理时依然会保留最近的一个版本，以免业务拉取不到镜像。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>垃圾回收 (&lt;code>garbage-collect&lt;/code>)&lt;/strong>：脚本删除标签后，镜像状态会变成 untagged（无标签），最后执行 &lt;code>registry garbage-collect --delete-untagged&lt;/code> 才会把它们真正从宿主机的物理硬盘上删除。&lt;/li>
&lt;li>&lt;strong>内网直连&lt;/strong>：脚本直接使用内网地址 &lt;code>http://my-private-registry:5000&lt;/code> 通信，既快又不会受到外部 Traefik 或 Nginx 超时策略的影响。&lt;/li>
&lt;/ol>
&lt;h2 id="filebrowser">FileBrowser
&lt;/h2>&lt;p>这份教程不仅能让你拥有一个管理 VPS 全盘文件的神器，还规避了密码无法重置、下载系统文件报错等常见问题。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>1. 准备工作&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>目标&lt;/strong>：部署一个 Web 端的文件管理器，可以管理 VPS 上的&lt;strong>所有文件&lt;/strong>（拥有 Root 权限）。&lt;/li>
&lt;li>&lt;strong>工具&lt;/strong>：Dokploy 面板（使用 Docker Compose 方式）。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 部署配置 (Docker Compose)&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 中创建一个新的 &lt;strong>Application (Compose)&lt;/strong>，将以下代码完整复制进去。&lt;/p>
&lt;p>&lt;strong>代码特点：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>超级权限&lt;/strong>：使用 &lt;code>user: &amp;quot;0:0&amp;quot;&lt;/code> 获得 Root 权限，可读写系统任何文件。&lt;/li>
&lt;li>&lt;strong>全盘挂载&lt;/strong>：将宿主机根目录 &lt;code>/&lt;/code> 挂载到容器内，实现全盘管理。&lt;/li>
&lt;li>&lt;strong>防止配置冲突&lt;/strong>：修正了之前的语法错误，并配置了数据卷以确保持久化。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.3&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">filebrowser&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">filebrowser/filebrowser:latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">filebrowser_root&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 核心：赋予容器 Root 权限，否则无法修改系统文件&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">user&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;0:0&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 核心：将 VPS 的根目录 (/) 挂载到容器的 /srv 目录&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">/:/srv&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 数据库持久化卷：存储你的用户信息和设置&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 如果忘记密码，修改冒号前的名称 (如改成 filebrowser_data_v3) 即可重置&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">filebrowser_data_v2:/database &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 启动命令 (合并写在一行)：&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># -d 指定数据库路径&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># -p 强制监听 80 端口&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># -r 指定根目录为挂载进来的 /srv&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>-&lt;span class="l">d /database/filebrowser.db -p 80 -r /srv&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 对应上面的数据卷名称&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">filebrowser_data_v2&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">dokploy-network&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">external&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. 端口设置 (Ports)&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 的应用设置界面，找到 &lt;strong>Ports&lt;/strong> 选项卡：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Internal Port (容器端口)&lt;/strong>: &lt;code>80&lt;/code>&lt;/li>
&lt;li>&lt;strong>External Port (外部端口)&lt;/strong>: 填写一个未被占用的端口，例如 &lt;code>8088&lt;/code> 或 &lt;code>9999&lt;/code>。&lt;/li>
&lt;/ul>
&lt;p>点击 &lt;strong>Save&lt;/strong> 并 &lt;strong>Deploy&lt;/strong>。&lt;/p>
&lt;p>&lt;strong>4. 首次登录与设置&lt;/strong>&lt;/p>
&lt;p>部署完成后，通过浏览器访问 &lt;code>http://你的 IP:你的外部端口&lt;/code>。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>默认账号&lt;/strong>：&lt;code>admin&lt;/code>&lt;/li>
&lt;li>&lt;strong>默认密码&lt;/strong>：&lt;code>admin&lt;/code>&lt;/li>
&lt;li>&lt;strong>修改密码（重要）&lt;/strong>：
&lt;ul>
&lt;li>登录后，点击左侧栏 &lt;strong>Settings&lt;/strong> -&amp;gt; &lt;strong>Profile&lt;/strong>。&lt;/li>
&lt;li>在 &lt;strong>Password&lt;/strong> 区域输入新密码。&lt;/li>
&lt;li>点击 &lt;strong>Update&lt;/strong> 保存。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>5. 避坑指南 (常见误区)&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Q1: 为什么下载某些文件报错 &lt;code>ERR_INVALID_RESPONSE&lt;/code>？&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：尝试下载 &lt;code>/proc&lt;/code>、&lt;code>/sys&lt;/code>、&lt;code>/dev&lt;/code> 目录下的文件时失败。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：这些不是真实文件，而是系统内存和内核状态的“虚拟映射”。它们大小通常显示为 0，Web 服务器无法打包下载它们。&lt;/li>
&lt;li>&lt;strong>解决&lt;/strong>：&lt;strong>不要下载这些目录的文件&lt;/strong>。请测试下载 &lt;code>/etc/hosts&lt;/code> 或者你自己创建的 &lt;code>/home/test.txt&lt;/code>，这些才是真实文件。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Q2: 我忘记了密码怎么办？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>无法通过环境变量设置密码&lt;/strong>。如果忘记密码，最快的方法是“洗号重来”：&lt;/p>
&lt;ol>
&lt;li>修改 Docker Compose 中的 &lt;code>volumes&lt;/code> 部分。&lt;/li>
&lt;li>将 &lt;code>- filebrowser_data_v2:/database&lt;/code> 改为 &lt;code>- filebrowser_data_v3:/database&lt;/code>。&lt;/li>
&lt;li>重新部署。这会生成全新的数据库，密码恢复为默认的 &lt;code>admin&lt;/code>。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Q3: 安全警告&lt;/strong>&lt;/p>
&lt;p>因为这个容器挂载了 &lt;code>/&lt;/code> 根目录且拥有 Root 权限：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>不要&lt;/strong>随意删除 &lt;code>/bin&lt;/code>, &lt;code>/boot&lt;/code>, &lt;code>/usr&lt;/code> 等系统核心目录，否则 VPS 会挂掉。&lt;/li>
&lt;li>&lt;strong>务必&lt;/strong>设置强密码，不要将此服务随意暴露给不可信的人。&lt;/li>
&lt;/ul>
&lt;h2 id="webdav">webDAV
&lt;/h2>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">webdav&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bytemark/webdav&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">AUTH_TYPE=Basic&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">USERNAME=your_username&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">PASSWORD=your_password&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./data:/var/lib/dav&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 1. 路由规则：域名匹配&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.webdav.rule=Host(`dav.yourdomain.com`)&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 2. 启用 TLS 并在入口点使用 HTTPS (443)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.webdav.entrypoints=websecure&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 3. 指定你的 Let&amp;#39;s Encrypt 解析器名称 (通常在 Traefik 全局配置里定义)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.routers.webdav.tls.certresolver=letsencrypt&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 4. 强制指定内部端口，防止 Traefik 误判&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;traefik.http.services.webdav.loadbalancer.server.port=80&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cleaner&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./data:/var/lib/dav&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">/bin/sh&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- -&lt;span class="l">c&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> while true; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 检查 1024MB (1GB)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> while [ $$(du -sm /var/lib/dav | awk &amp;#39;{print $$1}&amp;#39;) -gt 1024 ]; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 删掉最老的文件
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> OLDEST=$$(find /var/lib/dav -type f -exec stat -c &amp;#34;%Y %n&amp;#34; {} + | sort -n | head -n 1 | cut -d&amp;#34; &amp;#34; -f2-)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> [ -z &amp;#34;$$OLDEST&amp;#34; ] &amp;amp;&amp;amp; break
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> rm -f &amp;#34;$$OLDEST&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> sleep 60
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> done&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;p>&lt;strong>💡补充几点：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>证书解析器名称&lt;/strong>：
标签里的 &lt;code>tls.certresolver=letsencrypt&lt;/code>。这里的 &lt;code>letsencrypt&lt;/code> 必须和你 Traefik 静态配置文件（或是 Dokploy 设置里）定义的解析器名称&lt;strong>完全一致&lt;/strong>。如果不一致，证书不会自动签发。&lt;/li>
&lt;li>&lt;strong>网络（Network）的坑&lt;/strong>：
如果你发现域名访问报 &lt;strong>504 Gateway Timeout&lt;/strong>，那 99% 还是网络问题。此时你需要运行 &lt;code>docker network ls&lt;/code> 看看 Traefik 在哪个网段，并在 &lt;code>webdav&lt;/code> 服务下加上该网络。&lt;/li>
&lt;li>&lt;strong>关于清理脚本（Cleaner）&lt;/strong>：
这个脚本是并行的。WebDAV 负责写，Cleaner 负责巡逻。它们共享 &lt;code>./data&lt;/code> 卷，所以互不干扰。&lt;/li>
&lt;/ol>
&lt;h2 id="alist">alist
&lt;/h2>&lt;p>alist 直接可以在应用市场安装&lt;/p>
&lt;h1 id="使用与配置">使用与配置
&lt;/h1>&lt;h2 id="docker-swarm-切换advertise-addr">docker swarm 切换advertise addr
&lt;/h2>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker swarm init --force-new-cluster --advertise-addr &amp;lt;你的服务器IP&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>注意: 需要等待几分钟,等待dokploy重新启动&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-7.png"
width="1573"
height="379"
srcset="https://www.zata.cc/p/dokploy/images/index/image-7_hu18256622804942156503.png 480w, https://www.zata.cc/p/dokploy/images/index/image-7_hu2889444537278421097.png 1024w"
loading="lazy"
alt="切换advertise addr"
class="gallery-image"
data-flex-grow="415"
data-flex-basis="996px"
>&lt;/p>
&lt;hr>
&lt;p>如果你已经安装好了 Dokploy，并且它正在运行，此时你&lt;strong>绝对不能执行&lt;/strong> &lt;code>docker swarm leave&lt;/code>，否则就像我们前面说的，整个 Dokploy 连同你的数据库会瞬间灰飞烟灭。&lt;/p>
&lt;p>但是 Docker 官方提供了一个非常优雅的“无损更换网络”的隐藏指令！你可以通过强制基于当前状态创建一个新集群的方式，在不丢失任何服务和数据的情况下更改 IP。&lt;/p>
&lt;p>&lt;strong>核心命令：无损更改 Advertise IP&lt;/strong>&lt;/p>
&lt;p>在你的主节点（运行 Dokploy 面板的服务器）上，直接执行以下命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker swarm init --force-new-cluster --advertise-addr &amp;lt;你的内网IP&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>例如：&lt;code>docker swarm init --force-new-cluster --advertise-addr 10.0.0.5&lt;/code>&lt;/p>
&lt;p>&lt;strong>为什么这个命令有效且安全？&lt;/strong>&lt;/p>
&lt;p>这个命令里的 &lt;code>--force-new-cluster&lt;/code>（强制新建集群）是关键。它的底层逻辑是：提取当前 Swarm 的所有数据状态（包括 Dokploy 面板、Postgres 数据库、Traefik 路由以及你已经部署的所有应用），然后用你指定的新 IP 强行拉起一个新的集群配置。&lt;/p>
&lt;p>在这个过程中：&lt;/p>
&lt;ul>
&lt;li>你的底层容器和 Volume 数据卷&lt;strong>完全不会丢失&lt;/strong>。&lt;/li>
&lt;li>Dokploy 面板在短暂的重启后会&lt;strong>立刻恢复可用&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;p>操作后的确认与收尾工作&lt;/p>
&lt;p>更改完成后，你需要做两步检查：&lt;/p>
&lt;p>&lt;strong>第一步：确认 IP 已经更改成功&lt;/strong>&lt;/p>
&lt;p>运行以下命令查看当前节点的实际广播地址：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker info &lt;span class="p">|&lt;/span> grep &lt;span class="s2">&amp;#34;Node Address&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果输出显示的是你的内网 IP，说明网络通道已经成功切换到内网了。&lt;/p>
&lt;p>&lt;strong>第二步：重新连接子节点（重要！）&lt;/strong>&lt;/p>
&lt;p>如果你之前已经添加了其他子节点（Worker），由于你强制生成了新的集群状态（集群的隐藏 ID 已经变了），以前加入的旧子节点会&lt;strong>全部断开连接&lt;/strong>。你需要让它们重新加入：&lt;/p>
&lt;ol>
&lt;li>在主节点上获取新的加入令牌：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker swarm join-token worker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>（复制终端打印出来的那串新命令）&lt;/p>
&lt;ol start="2">
&lt;li>登录到所有的子节点服务器，先让它们强制退出旧网络，再加入新网络：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 先让子节点强制离开旧集群&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker swarm leave --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 然后粘贴你刚刚复制的加入命令，例如：&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker swarm join --token SWMTKN-1-xxxx &amp;lt;主节点内网IP&amp;gt;:2377
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="volume--vs-bind-mount-vs-environment-variables-----20260310">Volume vs Bind Mount vs Environment Variables &amp;mdash; 20260310
&lt;/h2>&lt;p>本教程旨在帮助您彻底理解 Dokploy 中的数据存储机制（Volumes）与环境变量（Environment Variables）的配置方式、区别及最佳实践。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>📋 第一部分：核心概念速查（决策树）&lt;/strong>&lt;/p>
&lt;p>在动手配置之前，请根据您的具体需求选择正确的存储类型：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">您的需求&lt;/th>
&lt;th style="text-align: left">推荐类型&lt;/th>
&lt;th style="text-align: left">关键特征&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>数据库数据&lt;/strong> (MySQL, PostgreSQL, Redis)&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>Volume (命名卷)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Docker 自动管理，权限无忧，备份迁移方便。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>用户上传的文件&lt;/strong> (图片/视频/附件)&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>Volume (命名卷)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">安全隔离，不依赖宿主机具体路径结构。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>简单的配置文件&lt;/strong> (&lt;code>.env&lt;/code>, &lt;code>config.json&lt;/code>, &lt;code>nginx.conf&lt;/code>)&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>File Mount (文件挂载)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">&lt;strong>最推荐&lt;/strong>。网页直接编写内容，无需 SSH，自动创建并挂载。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>复杂的配置目录&lt;/strong> (已有大量现有配置文件)&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>Bind Mount (绑定挂载)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">映射宿主机现有目录，适合高级用户或遗留系统迁移。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>开发调试/代码热更新&lt;/strong>&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>Bind Mount (绑定挂载)&lt;/strong>&lt;/td>
&lt;td style="text-align: left">宿主机修改代码/文件，容器内即时生效。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>不确定选哪个&lt;/strong>&lt;/td>
&lt;td style="text-align: left">✅ &lt;strong>Volume&lt;/strong>&lt;/td>
&lt;td style="text-align: left">它是 Docker 的最佳实践，容错率最高。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;p>&lt;strong>🛠️ 第二部分：三种存储类型详解与实战&lt;/strong>&lt;/p>
&lt;p>&lt;strong>1. Volume (命名卷) —— &amp;ldquo;让 Docker 操心&amp;rdquo;&lt;/strong>
&lt;strong>适用场景&lt;/strong>：数据库持久化、应用产生的数据文件。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>工作原理&lt;/strong>：Docker 在其专用目录（通常是 &lt;code>/var/lib/docker/volumes/&lt;/code>）下创建并管理存储空间。&lt;/li>
&lt;li>&lt;strong>优点&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>权限自动适配&lt;/strong>：极少出现 &lt;code>Permission denied&lt;/code> 错误。&lt;/li>
&lt;li>&lt;strong>高可移植性&lt;/strong>：不依赖宿主机的具体目录结构，迁移服务器只需迁移卷数据。&lt;/li>
&lt;li>&lt;strong>安全隔离&lt;/strong>：数据存储在 Docker 管理区域，不易被误删。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Dokploy 配置步骤&lt;/strong>：
&lt;ol>
&lt;li>进入应用 &lt;strong>Advanced&lt;/strong> -&amp;gt; &lt;strong>Volumes&lt;/strong>。&lt;/li>
&lt;li>点击 &lt;strong>Add Volume&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>Mount Type&lt;/strong>: 选择 &lt;code>Volume&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Name&lt;/strong>: 输入卷名称（如 &lt;code>db_data&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>Mount Path&lt;/strong>: 输入容器内路径（如 &lt;code>/var/lib/postgresql/data&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>Host Path&lt;/strong>: &lt;strong>留空&lt;/strong>。&lt;/li>
&lt;li>保存并 &lt;strong>Deploy&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. File Mount (文件挂载) —— &amp;ldquo;网页即写即用&amp;rdquo;&lt;/strong>
&lt;strong>适用场景&lt;/strong>：单个配置文件（&lt;code>.env&lt;/code>, &lt;code>.conf&lt;/code>, &lt;code>.json&lt;/code>）。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>工作原理&lt;/strong>：Dokploy 将您在网页文本框中输入的内容，在后台动态生成一个临时文件，并挂载到容器指定路径。&lt;/li>
&lt;li>&lt;strong>优点&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>无需 SSH&lt;/strong>：直接在面板编辑，无需登录服务器创建文件。&lt;/li>
&lt;li>&lt;strong>版本友好&lt;/strong>：内容直接保存在 Dokploy 配置中，便于管理。&lt;/li>
&lt;li>&lt;strong>简单快捷&lt;/strong>：最适合 &lt;code>.env&lt;/code> 文件管理。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Dokploy 配置步骤&lt;/strong>：
&lt;ol>
&lt;li>进入应用 &lt;strong>Advanced&lt;/strong> -&amp;gt; &lt;strong>Volumes&lt;/strong>。&lt;/li>
&lt;li>点击 &lt;strong>Add Volume&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>Mount Type&lt;/strong>: 选择 &lt;code>File Mount&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Content&lt;/strong>: 粘贴文件完整内容。&lt;/li>
&lt;li>&lt;strong>File Path&lt;/strong>: 输入容器内&lt;strong>完整文件路径&lt;/strong>（必须包含文件名，如 &lt;code>/app/.env&lt;/code>）。&lt;/li>
&lt;li>保存并 &lt;strong>Deploy&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. Bind Mount (绑定挂载) —— &amp;ldquo;完全由你控制&amp;rdquo;&lt;/strong>
&lt;strong>适用场景&lt;/strong>：挂载现有目录、代码热重载、访问宿主机特定资源。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>工作原理&lt;/strong>：将容器路径直接映射到宿主机上已存在的绝对路径。&lt;/li>
&lt;li>&lt;strong>优点&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>路径透明&lt;/strong>：可直接在宿主机通过 SSH/FTP 访问和编辑文件。&lt;/li>
&lt;li>&lt;strong>实时同步&lt;/strong>：宿主机文件修改，容器内立即生效（适合开发）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>缺点&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>权限陷阱&lt;/strong>：需手动确保宿主机文件夹权限与容器用户匹配。&lt;/li>
&lt;li>&lt;strong>路径依赖&lt;/strong>：迁移服务器时需重建相同的目录结构。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>前置准备&lt;/strong>（SSH 登录服务器）：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir -p /home/dokploy/my-app/logs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod &lt;span class="m">777&lt;/span> /home/dokploy/my-app/logs &lt;span class="c1"># 注意权限设置&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>Dokploy 配置步骤&lt;/strong>：
&lt;ol>
&lt;li>进入应用 &lt;strong>Advanced&lt;/strong> -&amp;gt; &lt;strong>Volumes&lt;/strong>。&lt;/li>
&lt;li>点击 &lt;strong>Add Volume&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>Mount Type&lt;/strong>: 选择 &lt;code>Bind&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Host Path&lt;/strong>: 填写宿主机&lt;strong>绝对路径&lt;/strong>（如 &lt;code>/home/dokploy/my-app/logs&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>Mount Path&lt;/strong>: 填写容器内路径（如 &lt;code>/app/logs&lt;/code>）。&lt;/li>
&lt;li>保存并 &lt;strong>Deploy&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>&lt;strong>⚖️ 第三部分：环境变量 (Env) 的两种配置方式及优先级&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 中，您有两种方式向容器传递配置信息，理解它们的区别至关重要。&lt;/p>
&lt;p>&lt;strong>1. 两种方式对比&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">特性&lt;/th>
&lt;th style="text-align: left">&lt;strong>控制面板 Env 设置&lt;/strong>&lt;/th>
&lt;th style="text-align: left">&lt;strong>挂载 .env 文件 (File Mount)&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>操作位置&lt;/strong>&lt;/td>
&lt;td style="text-align: left">应用菜单 -&amp;gt; &lt;strong>Environment&lt;/strong> 标签页&lt;/td>
&lt;td style="text-align: left">应用菜单 -&amp;gt; &lt;strong>Advanced&lt;/strong> -&amp;gt; &lt;strong>Volumes&lt;/strong> -&amp;gt; &lt;strong>File Mount&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>底层原理&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Docker 启动参数 &lt;code>-e KEY=VALUE&lt;/code>&lt;/td>
&lt;td style="text-align: left">文件系统挂载 &lt;code>-v host_file:/container/.env&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>生效机制&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Docker 守护进程直接注入进程环境空间&lt;/td>
&lt;td style="text-align: left">&lt;strong>应用程序自己读取文件&lt;/strong>解析加载&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>适用框架&lt;/strong>&lt;/td>
&lt;td style="text-align: left">所有支持环境变量的应用&lt;/td>
&lt;td style="text-align: left">支持读取 &lt;code>.env&lt;/code> 文件的框架 (Node.js, Python, Laravel 等)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>管理体验&lt;/strong>&lt;/td>
&lt;td style="text-align: left">适合少量、分散的变量&lt;/td>
&lt;td style="text-align: left">适合大量、成组的配置，与本地开发一致&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>2. 优先级冲突：如果两个地方都设置了同一个变量，谁生效？&lt;/strong>&lt;/p>
&lt;p>&lt;strong>答案取决于您的应用程序代码逻辑，而非 Docker。&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>情况 A：现代框架 (Node.js &lt;code>dotenv&lt;/code>, Python &lt;code>python-dotenv&lt;/code>, Laravel)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>通常加载顺序：先读 &lt;code>.env&lt;/code> 文件 -&amp;gt; 再读系统环境变量。&lt;/li>
&lt;li>&lt;strong>常见行为&lt;/strong>：系统环境变量（控制面板设置）&lt;strong>覆盖&lt;/strong> &lt;code>.env&lt;/code> 文件中的值。&lt;/li>
&lt;li>&lt;strong>部分行为&lt;/strong>：某些配置下，&lt;code>.env&lt;/code> 文件一旦加载即锁定，环境变量无法覆盖。&lt;/li>
&lt;li>&lt;em>风险&lt;/em>：混用会导致配置行为不可预测，难以排查。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>情况 B：传统应用 (Nginx, Redis, Go/C 编译程序)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>这些程序通常&lt;strong>不会自动读取 &lt;code>.env&lt;/code> 文件&lt;/strong>。&lt;/li>
&lt;li>它们只认&lt;strong>系统环境变量&lt;/strong>（控制面板设置）或特定的配置文件（如 &lt;code>nginx.conf&lt;/code>）。&lt;/li>
&lt;li>&lt;em>结论&lt;/em>：对于这类应用，挂载 &lt;code>.env&lt;/code> 文件通常&lt;strong>无效&lt;/strong>，必须使用控制面板 Env 或直接挂载对应的 conf 文件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. 💡 最佳实践建议&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>二选一原则&lt;/strong>：针对同一组配置，&lt;strong>不要混用&lt;/strong>两种方式。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>方案 A（推荐用于 Web 应用）&lt;/strong>：完全使用 &lt;strong>File Mount&lt;/strong> 挂载完整的 &lt;code>.env&lt;/code> 文件。
&lt;ul>
&lt;li>&lt;em>理由&lt;/em>：保证本地开发环境与生产环境配置文件完全一致，复制粘贴即可，减少人为遗漏。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>方案 B（推荐用于基础服务/简单变量）&lt;/strong>：完全使用 &lt;strong>控制面板 Env 设置&lt;/strong>。
&lt;ul>
&lt;li>&lt;em>理由&lt;/em>：界面清晰，管理方便，适合变量较少的情况。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>明确应用行为&lt;/strong>：查阅应用文档，确认它是优先读取文件还是优先读取环境变量。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>敏感信息&lt;/strong>：如果极度敏感，考虑使用 &lt;strong>Bind Mount&lt;/strong> 挂载服务器上权限严格控制的独立文件，避免内容出现在 Dokploy 数据库备份中。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>⚠️ 第四部分：常见陷阱与故障排查&lt;/strong>&lt;/p>
&lt;p>&lt;strong>1. 权限错误 (Permission Denied)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：容器启动失败，日志提示无法写入文件或读取配置。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：多见于 &lt;strong>Bind Mount&lt;/strong>。容器内用户 UID 与宿主机文件夹所有者不一致。&lt;/li>
&lt;li>&lt;strong>解决&lt;/strong>：
&lt;ul>
&lt;li>优先改用 &lt;strong>Volume&lt;/strong>。&lt;/li>
&lt;li>若必须用 Bind，在服务器执行 &lt;code>chown -R &amp;lt;UID&amp;gt;:&amp;lt;GID&amp;gt; /host/path&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 路径错误&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>File Mount&lt;/strong>：&lt;code>File Path&lt;/code> 必须是&lt;strong>完整路径 + 文件名&lt;/strong>（例：&lt;code>/app/.env&lt;/code>），不能只是目录。&lt;/li>
&lt;li>&lt;strong>Bind Mount&lt;/strong>：&lt;code>Host Path&lt;/code> 必须是&lt;strong>绝对路径&lt;/strong>，不能用 &lt;code>~&lt;/code> 或相对路径。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. 修改未生效&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>File Mount / Env Panel&lt;/strong>：修改后必须点击 &lt;strong>Deploy&lt;/strong> 重新创建/启动容器。&lt;/li>
&lt;li>&lt;strong>Bind Mount&lt;/strong>：文件修改通常即时生效，但&lt;strong>应用程序可能需要重启&lt;/strong>才能重新加载配置（除非支持热重载）。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>4. 数据迁移&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Volume&lt;/strong>：需使用 Docker 命令或 Dokploy 备份功能迁移卷数据。&lt;/li>
&lt;li>&lt;strong>Bind Mount&lt;/strong>：直接打包宿主机对应文件夹 (&lt;code>tar&lt;/code>) 传输到新服务器即可。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>&lt;strong>🏁 总结流程图&lt;/strong>&lt;/p>
&lt;div class="mermaid">
graph TD
Start[开始配置存储] --&amp;gt; Q1{数据类型？}
Q1 -- 数据库/持久化数据 --&amp;gt; Vol[使用 Volume&amp;lt;br&amp;gt;安全/自动管理]
Q1 -- 单个配置文件 (.env) --&amp;gt; File[使用 File Mount&amp;lt;br&amp;gt;网页编辑/最便捷]
Q1 -- 现有目录/代码热更 --&amp;gt; Bind[使用 Bind Mount&amp;lt;br&amp;gt;需 SSH 预建目录]
File --&amp;gt; EnvQ{是否需要设置环境变量？}
EnvQ -- 是 --&amp;gt; Choice{选择策略}
Choice -- 推荐：保持一致性 --&amp;gt; UseFile[完全使用 File Mount 挂载 .env]
Choice -- 备选：简单变量 --&amp;gt; UsePanel[完全使用 控制面板 Env 设置]
Choice -- ❌ 禁止 --&amp;gt; Mix[&amp;#34;混用两者 (易导致冲突)&amp;#34;]
Vol --&amp;gt; Deploy[点击 Deploy 部署]
Bind --&amp;gt; Deploy
UseFile --&amp;gt; Deploy
UsePanel --&amp;gt; Deploy
Deploy --&amp;gt; Done[完成]
&lt;/div>
&lt;p>遵循本指南，您将能够高效、安全地管理 Dokploy 中的应用数据与配置。如有具体报错，请提供日志以便进一步分析。&lt;/p>
&lt;h2 id="dokploy-自动化部署踩坑">Dokploy 自动化部署踩坑
&lt;/h2>&lt;p>在使用 Dokploy 配合 CI/CD（如 GitHub Actions）进行自动化部署时，很多人会踩到两个致命的坑：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>时序错乱（抢跑）&lt;/strong>：刚 git push 完代码，CI/CD 还没把镜像打包推送完，Dokploy 就已经提前开始拉取部署了，导致部署失败或拉到旧镜像。&lt;/li>
&lt;li>&lt;strong>镜像缓存（死不更新）&lt;/strong>：等镜像真正推送完，去触发 Dokploy Webhook 时，由于镜像标签都是 latest，Dokploy 直接用了本地缓存，怎么部署都是旧版本！&lt;/li>
&lt;/ul>
&lt;p>今天，我们就用 &lt;strong>“Raw 模式分离” + “API 改写镜像 SHA”&lt;/strong> 的终极方案，彻底打通这条全自动流水线！&lt;/p>
&lt;p>&lt;strong>踩坑一：为什么一 Push 代码 Dokploy 就抢跑？&lt;/strong>&lt;/p>
&lt;p>根本原因：如果你在 Dokploy 中选择了 Git 作为代码源，它的触发器只有 On Push，一旦侦测到代码提交它就会立刻执行。&lt;/p>
&lt;p>破局思路：既然镜像已经由 CI/CD 负责打包，Dokploy 就只需要做一个“纯粹的执行器”。&lt;/p>
&lt;p>👉 &lt;strong>解决方法：&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 的应用设置中，不要选 Git/GitHub。&lt;/p>
&lt;ul>
&lt;li>如果是单容器，数据源选 &lt;strong>Docker&lt;/strong>。&lt;/li>
&lt;li>如果是编排部署，数据源选 &lt;strong>Raw 模式&lt;/strong>（直接粘贴你的 docker-compose.yml）。&lt;/li>
&lt;/ul>
&lt;p>这样 Dokploy 就彻底脱离了 Git 仓库的束缚，只会安静等待指令。&lt;/p>
&lt;p>&lt;strong>踩坑二：触发更新时，如何彻底避免 latest 镜像缓存？&lt;/strong>&lt;/p>
&lt;p>很多教程只教你推完镜像后 curl 一下 Webhook，但这不够。为了实现绝对的不可变部署（Immutable Deployment），最佳实践是在 CI/CD 构建完镜像后，提取该镜像唯一的 SHA 摘要（Digest），利用 Dokploy 的 API 动态改写配置，然后再触发部署。&lt;/p>
&lt;p>&lt;strong>准备工作：获取 API 密钥与 URL&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>生成 API Key&lt;/strong>：登录 Dokploy 面板，点击右上角头像 -&amp;gt; Profile -&amp;gt; 找到 API/CLI 区域，生成一串 API Key。&lt;/li>
&lt;li>&lt;strong>确认 API URL&lt;/strong>：即你的 Dokploy 访问地址（例如 &lt;code>https://dokploy.your-domain.com&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>获取应用 ID&lt;/strong>：在 Dokploy 中点开你的应用，看浏览器地址栏，通常能找到你的 &lt;code>applicationId&lt;/code> 或 &lt;code>composeId&lt;/code>。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>终极 CI/CD 流水线实战（以 GitHub Actions 为例）&lt;/strong>&lt;/p>
&lt;p>我们需要在工作流中完成三个步骤：构建推送 -&amp;gt; 改写 Dokploy 配置里的 SHA -&amp;gt; 触发部署。&lt;/p>
&lt;p>在你的 &lt;code>.github/workflows/deploy.yml&lt;/code> 最后加上这段核心代码：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 前置步骤：正常拉取代码并登录镜像库...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">构建并推送 Docker 镜像，提取 SHA&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">build-image&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 1. 正常打包并推送最新镜像
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> docker build -t your-namespace/your-image:latest .
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> docker push your-namespace/your-image:latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 2. 核心操作：获取刚刚推送在云端生成的唯一 SHA256 摘要&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">IMAGE_SHA=$(docker inspect --format=&amp;#39;{{index .RepoDigests 0}}&amp;#39; your-namespace/your-image:latest)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;IMAGE_SHA=$IMAGE_SHA&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">echo &amp;#34;最新镜像摘要为: $IMAGE_SHA&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">调用 Dokploy API 改写镜像 SHA&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 3. 将带有 SHA 的完整镜像地址更新到 Dokploy 的配置中
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> curl -X POST &amp;#34;https://dokploy.your-domain.com/api/application.update&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -H &amp;#34;Authorization: Bearer ${{ secrets.DOKPLOY_API_KEY }}&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -H &amp;#34;Content-Type: application/json&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -d &amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> &amp;#34;applicationId&amp;#34;: &amp;#34;${{ secrets.DOKPLOY_APP_ID }}&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> &amp;#34;dockerImage&amp;#34;: &amp;#34;${{ env.IMAGE_SHA }}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> }&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">调用 Dokploy API 触发真实部署&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> # 4. 配置修改完毕，正式下达部署指令
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> curl -X POST &amp;#34;https://dokploy.your-domain.com/api/application.deploy&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -H &amp;#34;Authorization: Bearer ${{ secrets.DOKPLOY_API_KEY }}&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -H &amp;#34;Content-Type: application/json&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -d &amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> &amp;#34;applicationId&amp;#34;: &amp;#34;${{ secrets.DOKPLOY_APP_ID }}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> }&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(💡 提示：记得在 GitHub 的 Secrets 中配置好 &lt;code>DOKPLOY_API_KEY&lt;/code> 和 &lt;code>DOKPLOY_APP_ID&lt;/code>)&lt;/p>
&lt;p>&lt;strong>💡 进阶技巧：如果你用的是 Raw 模式 (Docker Compose) 怎么办？&lt;/strong>&lt;/p>
&lt;p>在 Raw 模式下由于是直接写 YAML 文件，API 更新全文有些繁琐。最佳实践是结合环境变量：&lt;/p>
&lt;p>在 Dokploy 的 Raw 配置框中这样写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">web&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">your-namespace/your-image@${IMAGE_SHA}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 引用环境变量&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在 GitHub Actions 中，调用 Dokploy 的环境变量更新 API（&lt;code>/api/application.env.set&lt;/code> 或相关路由），把新的 SHA 刷进环境变量里。最后再触发 Deploy。&lt;/p>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;p>通过上述改造，我们完美分离了“代码构建”与“容器部署”的职责：&lt;/p>
&lt;ul>
&lt;li>CI/CD 专职负责构建镜像，并产出带有唯一指纹的 SHA 摘要。&lt;/li>
&lt;li>Dokploy 作为纯粹的容器执行引擎，通过 API 接收最新的 SHA 彻底绕过本地缓存。&lt;/li>
&lt;/ul>
&lt;p>时序绝对正确，更新绝对精准，你的全自动 CI/CD 部署流水线现在坚不可摧了！🎉&lt;/p>
&lt;h2 id="解决-traefik-处理大文件上传时的-502-错误-io-timeout">解决 Traefik 处理大文件上传时的 502 错误 (i/o timeout)
&lt;/h2>&lt;p>在使用 Traefik 作为反向代理时，如果遇到大文件上传导致 &lt;code>502 Bad Gateway&lt;/code> 错误，且日志中出现 &lt;code>i/o timeout&lt;/code> 相关信息，通常是因为 Traefik 的默认超时设置过短。&lt;/p>
&lt;p>以下是具体的排查思路与解决方案。&lt;/p>
&lt;p>&lt;strong>1. 问题现象与日志分析&lt;/strong>&lt;/p>
&lt;p>当上传较大文件时，请求在到达后端之前被 Traefik 截断，返回 502 错误。查看 Traefik 容器日志，关键错误信息如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">vulcand/oxy/buffer: error when reading request body, err: i/o timeout
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">entryPointName=websecure middlewareName=transmaster-staging-backend-buffering@docker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>原因定位：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>错误并非由 &lt;code>maxRequestBodyBytes&lt;/code>（请求体大小限制）引起。&lt;/li>
&lt;li>根本原因是 Traefik 的 &lt;code>buffering&lt;/code> 中间件在等待客户端上传数据时发生了 &lt;strong>I/O 超时 (i/o timeout)&lt;/strong>。默认的读取超时时间对于大文件上传来说太短了。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 解决方案&lt;/strong>&lt;/p>
&lt;p>需要修改 &lt;code>traefik.yml&lt;/code> 配置文件，在对应的 &lt;code>entryPoints&lt;/code>（入口点）下增加 &lt;code>respondingTimeouts&lt;/code> 配置，延长读取和写入的超时时间。&lt;/p>
&lt;p>&lt;strong>修改 &lt;code>traefik.yml&lt;/code>&lt;/strong>&lt;/p>
&lt;p>找到你的 &lt;code>traefik.yml&lt;/code> 文件（通常位于 &lt;code>/etc/dokploy/traefik/traefik.yml&lt;/code> 或类似路径），在 &lt;code>entryPoints&lt;/code> 部分添加或修改 &lt;code>transport&lt;/code> 配置。&lt;/p>
&lt;p>&lt;strong>配置示例：&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">entryPoints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">web&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">transport&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">respondingTimeouts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">readTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">900s &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 读取请求体超时时间（针对大文件上传，建议设大一点，如 15 分钟）&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">writeTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">900s &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 写入响应超时时间&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">idleTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">180s &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 空闲连接超时时间&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">websecure&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">address&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="m">443&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">transport&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">respondingTimeouts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">readTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">900s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">writeTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">900s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">idleTimeout&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">180s&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">http&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tls&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">certResolver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">letsencrypt&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>参数说明：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>readTimeout&lt;/code>: 最关键参数。决定 Traefik 等待客户端把请求体传完的时间。如果上传文件较大或网速较慢，需适当调大（例如 900s）。&lt;/li>
&lt;li>&lt;code>writeTimeout&lt;/code>: 决定 Traefik 等待后端服务返回响应的时间。&lt;/li>
&lt;li>&lt;code>idleTimeout&lt;/code>: 保持连接空闲的超时时间，通常不需要太大。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>3. 应用配置&lt;/strong>&lt;/p>
&lt;p>修改保存配置文件后，需要重启 Traefik 容器以使配置生效。&lt;/p>
&lt;p>&lt;strong>执行重启命令：&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker restart dokploy-traefik
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// 或者根据你的容器名称调整，例如：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// docker restart &amp;lt;traefik_container_name&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>4. 验证结果&lt;/strong>&lt;/p>
&lt;p>重启完成后，再次尝试上传之前失败的大文件。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>观察日志：&lt;/strong> 确认不再出现 &lt;code>i/o timeout&lt;/code> 错误。&lt;/li>
&lt;li>&lt;strong>业务测试：&lt;/strong> 文件上传成功，不再返回 502 错误。&lt;/li>
&lt;/ul>
&lt;p>通过调整 &lt;code>respondingTimeouts&lt;/code>，即可解决因网络波动或文件过大导致的 Traefik 上传超时问题。&lt;/p>
&lt;h2 id="部署相同项目的但是不同的环境staging和production发现冲突-----trakfik路由重名冲突问题">部署相同项目的但是不同的环境（staging和production）发现冲突 &amp;mdash; trakfik路由重名冲突问题
&lt;/h2>&lt;p>在 Dokploy 中，路由重名问题（Route Name Collision / Duplicate Route）是一个在部署多个应用或同一应用的多个实例时经常遇到的网络路由冲突问题。&lt;/p>
&lt;p>要理解这个问题，首先需要了解 Dokploy 的底层网络架构：Dokploy 依赖 Traefik 作为其反向代理和负载均衡器。Traefik 通过读取 Docker 容器上的标签（Labels）或动态配置文件，来决定如何将外部的 HTTP/HTTPS 请求转发到正确的内部容器。&lt;/p>
&lt;p>以下是关于 Dokploy 中路由重名问题的详细解释：&lt;/p>
&lt;p>&lt;strong>什么是“路由重名”？&lt;/strong>&lt;/p>
&lt;p>在 Traefik 的配置体系中，每个路由规则都需要一个唯一的路由名称（Router Name）。例如，在 Docker Compose 的 labels 中，你可能会看到这样的配置：&lt;code>traefik.http.routers.my-app-router.rule=Host('example.com')&lt;/code>。这里的 &lt;code>my-app-router&lt;/code> 就是路由名称。如果在 Dokploy 中，有两个不同的服务或应用使用了完全相同的路由名称，Traefik 就会发生冲突。&lt;/p>
&lt;p>&lt;strong>常见的触发场景&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>部署同一模板的多个实例（多租户场景）：&lt;/strong> 假设你使用 Docker Compose 模板在 Dokploy 上部署了一个开源系统（如 ERPNext、WordPress 或你自己的项目）。当你想要为另一个客户部署第二套相同的系统时，如果你直接复制了 Compose 文件而没有修改里面的 Traefik 标签，两个容器都会声明自己叫 &lt;code>my-app-router&lt;/code>。&lt;/li>
&lt;li>&lt;strong>误绑重复的域名：&lt;/strong> 团队成员在 Dokploy 的控制面板中，不小心为两个不同的应用程序绑定了相同的域名（在 Dokploy 的 GitHub 仓库中，Issue #3036 专门提到了缺少重复域名校验导致的 Traefik 路由崩溃问题）。&lt;/li>
&lt;li>&lt;strong>服务从其他平台迁移时的硬编码：&lt;/strong> 直接复制了原本在 Coolify 或纯 Docker 环境下的 Compose 文件，导致不同项目复用了默认的通用路由名称（如 &lt;code>web-router&lt;/code> 或 &lt;code>frontend-router&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>路由重名会导致的后果&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>流量串门 / 覆盖失效：&lt;/strong> Traefik 无法区分这两个服务。通常情况下，后启动的容器可能会覆盖先启动的容器的路由规则，导致访问应用 A 的域名却打开了应用 B 的页面。&lt;/li>
&lt;li>&lt;strong>服务不可用（504 或 404 错误）：&lt;/strong> Traefik 的动态配置加载可能会因为命名冲突而报错，导致该路由规则被整体丢弃，最终访问域名时出现 504 Gateway Timeout 或 404 Not Found。&lt;/li>
&lt;li>&lt;strong>部署状态假死：&lt;/strong> Dokploy 面板显示应用已成功部署且正在运行，但外部始终无法通过域名访问。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>如何解决和避免？&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>方法一：确保路由名称的唯一性（最核心）&lt;/strong>
如果你通过 Templates 或 Docker Compose 部署应用，必须确保 labels 里的 router 和 service 名称是全局唯一的。
&lt;ul>
&lt;li>错误写法（写死名称）：&lt;code>- &amp;quot;traefik.http.routers.web-router.rule=...&amp;quot;&lt;/code>&lt;/li>
&lt;li>正确写法（添加唯一标识/租户 ID）：&lt;code>- &amp;quot;traefik.http.routers.app1-web-router.rule=...&amp;quot;&lt;/code> 或 &lt;code>- &amp;quot;traefik.http.routers.app2-web-router.rule=...&amp;quot;&lt;/code>&lt;/li>
&lt;li>或者使用环境变量：&lt;code>- &amp;quot;traefik.http.routers.${TENANT_ID}-router.rule=...&amp;quot;&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>方法二：明确指定 Traefik 网络&lt;/strong>
当出现复杂的网络配置时（例如应用同时加入了多个 Docker Network），Traefik 会不知道该把流量发往哪个网络，从而引发 504 错误。在标签中明确指定 Dokploy 的默认网络可以防范此类路由异常：&lt;code>- &amp;quot;traefik.docker.network=dokploy-network&amp;quot;&lt;/code>。&lt;/li>
&lt;li>&lt;strong>方法三：使用 Dokploy 原生 Application 部署&lt;/strong>
如果你使用的是 Dokploy 的 Applications 功能（基于 Nixpacks, Dockerfile 或 Buildpacks 部署），Dokploy 底层会通过修改 Traefik 的文件系统（File Provider）来自动为你生成带有唯一哈希值的路由名称。这种模式下，只要你不绑定完全重复的域名，通常不会触发路由重名问题。&lt;/li>
&lt;/ul>
&lt;p>总结：Dokploy 的路由重名本质上是 Traefik 代理引擎的命名空间冲突。在编写 Compose 文件或打标签时，养成为所有 Traefik 相关的 router、service、middlewares 加上项目名前缀的习惯，就能完美避开这个问题。&lt;/p>
&lt;p>&lt;strong>参考资料&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>cherryservers.com&lt;/li>
&lt;li>dokploy.com&lt;/li>
&lt;li>frappe.io&lt;/li>
&lt;li>github.com&lt;/li>
&lt;li>lobehub.com&lt;/li>
&lt;li>Google Search Suggestions: &amp;ldquo;dokploy&amp;rdquo; router name collision, &amp;ldquo;dokploy&amp;rdquo; route name, &amp;ldquo;dokploy&amp;rdquo; 路由冲突，&amp;ldquo;dokploy&amp;rdquo; duplicate route&lt;/li>
&lt;/ul>
&lt;h2 id="dokploy-如果因为磁盘爆了而崩溃怎么解决">dokploy 如果因为磁盘爆了而崩溃，怎么解决
&lt;/h2>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 确认磁盘状态&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">df -h
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 清除陈旧的系统日志&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo journalctl --vacuum-time&lt;span class="o">=&lt;/span>1d
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo journalctl --vacuum-size&lt;span class="o">=&lt;/span>100M
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 清理未使用的 Docker 镜像和停止的容器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker system prune -a -f
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="配置s3-destinations">配置S3 Destinations
&lt;/h2>&lt;ul>
&lt;li>以b2_buckets 为例&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>将 Backblaze B2 配置到 Dokploy 的 S3 存储指南&lt;/strong>&lt;/p>
&lt;p>将 Backblaze B2 配置到 Dokploy 的 S3 存储中主要分为两步：首先在 Backblaze 获取凭据，然后在 Dokploy 仪表板中完成设置。&lt;/p>
&lt;p>&lt;strong>第一步：在 Backblaze B2 中获取信息&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>创建存储桶 (Bucket)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>登录 Backblaze，进入 B2 Cloud Storage &amp;gt; Buckets。&lt;/li>
&lt;li>创建一个新存储桶（例如命名为 &lt;code>dokploy-backups&lt;/code>）。&lt;/li>
&lt;li>注意：在存储桶列表中找到刚才创建的桶，复制其显示的 S3 Endpoint（例如 &lt;code>s3.us-west-002.backblazeb2.com&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>创建应用程序密钥 (Application Keys)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>进入 App Keys 页面。&lt;/li>
&lt;li>点击 Add a New Application Key。&lt;/li>
&lt;li>设置名称，并确保权限设置为 Read and Write。&lt;/li>
&lt;li>创建后，你会得到：
&lt;ul>
&lt;li>&lt;code>keyID&lt;/code>（即 Dokploy 中的 Access Key）&lt;/li>
&lt;li>&lt;code>applicationKey&lt;/code>（即 Dokploy 中的 Secret Key）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>注意：&lt;code>applicationKey&lt;/code> 仅显示一次，请务必保存。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>第二步：在 Dokploy 中进行配置&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>进入 Dokploy 面板，点击左侧菜单的 Settings (设置)。&lt;/li>
&lt;li>找到 S3 Destinations 选项卡，点击 Add S3 Destination。&lt;/li>
&lt;li>根据以下对应关系填写表单：&lt;/li>
&lt;/ol>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Dokploy 字段&lt;/th>
&lt;th style="text-align: left">对应 Backblaze 的信息&lt;/th>
&lt;th style="text-align: left">示例值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">Name&lt;/td>
&lt;td style="text-align: left">自定义名称&lt;/td>
&lt;td style="text-align: left">Backblaze-B2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Provider&lt;/td>
&lt;td style="text-align: left">&lt;/td>
&lt;td style="text-align: left">选择 Amazon Web Services （AWS）S3 ｜&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Endpoint&lt;/td>
&lt;td style="text-align: left">存储桶页面的 S3 Endpoint (需带 https://)&lt;/td>
&lt;td style="text-align: left">&lt;code>https://s3.us-west-002.backblazeb2.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Region&lt;/td>
&lt;td style="text-align: left">Endpoint 中的地区部分&lt;/td>
&lt;td style="text-align: left">&lt;code>us-west-002&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Bucket&lt;/td>
&lt;td style="text-align: left">你创建的存储桶名称&lt;/td>
&lt;td style="text-align: left">&lt;code>dokploy-backups&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Access Key&lt;/td>
&lt;td style="text-align: left">刚才生成的 keyID&lt;/td>
&lt;td style="text-align: left">&lt;code>002123456789...&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Secret Key&lt;/td>
&lt;td style="text-align: left">刚才生成的 applicationKey&lt;/td>
&lt;td style="text-align: left">&lt;code>K001abcd...&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ol start="4">
&lt;li>&lt;strong>保存并测试&lt;/strong>：填写完成后，点击 Test Connection。如果显示成功，则说明配置正确。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>第三步：为数据库或应用开启备份&lt;/strong>&lt;/p>
&lt;p>配置好 S3 目的地后，你还需要将其应用到具体的备份任务中：&lt;/p>
&lt;ol>
&lt;li>进入你想备份的 Database (数据库) 或 Service。&lt;/li>
&lt;li>点击 Backups 选项卡。&lt;/li>
&lt;li>在 Select Destination 下拉菜单中选择刚才创建的 Backblaze-B2。&lt;/li>
&lt;li>设置 Cron Schedule（例如 &lt;code>0 0 * * *&lt;/code> 表示每天午夜备份）并启用。&lt;/li>
&lt;/ol>
&lt;p>** 第四步：恢复备份**&lt;/p>
&lt;p>总结恢复步骤清单：&lt;/p>
&lt;p>本地已经部署镜像并启动容器，对应需要恢复的卷名是 9cut8x_postgres_data。&lt;/p>
&lt;ol>
&lt;li>命令行查卷(这个卷名换成实际的)：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker ps -a --filter &lt;span class="nv">volume&lt;/span>&lt;span class="o">=&lt;/span>9cut8x_postgres_data
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>清理现场： docker rm -f &amp;lt;查到的容器ID&amp;gt;&lt;/li>
&lt;li>彻底删除旧卷： docker volume rm 9cut8x_postgres_data&lt;/li>
&lt;li>执行恢复： 在 Dokploy 的 Volume Backups 页面填入 9cut8x_postgres_data 并点击 Restore。&lt;/li>
&lt;li>验证： 恢复完成后，执行 docker volume ls 确保该卷已重新创建。&lt;/li>
&lt;li>部署应用： 回到 Dokploy 对应的服务界面，点击 &amp;ldquo;Deploy&amp;rdquo;（这会根据你的 docker-compose.yml 重新挂载刚才恢复好的卷）。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>常见问题排查&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>权限错误&lt;/strong>：确保创建 Key 时勾选了对应存储桶的 &amp;ldquo;Read and Write&amp;rdquo; 权限。&lt;/li>
&lt;li>&lt;strong>Endpoint 格式&lt;/strong>：Dokploy 通常需要完整的 URL 格式，请确保包含 &lt;code>https://&lt;/code>。&lt;/li>
&lt;li>&lt;strong>地区 (Region)&lt;/strong>：Backblaze 的地区代码通常就在 Endpoint URL 中（如 &lt;code>us-west-002&lt;/code>），必须准确填写。&lt;/li>
&lt;/ul>
&lt;h2 id="dokploy-swarm-子节点联通性测试指南">Dokploy Swarm 子节点联通性测试指南
&lt;/h2>&lt;p>这是一份专为 Dokploy 用户准备的 &lt;strong>Docker Swarm 子节点（Worker Node）联通性测试教程&lt;/strong>。在搭建好 Dokploy 多节点集群后，最关键的一步是验证 &lt;strong>管理节点（Manager）&lt;/strong> 是否能通过 &lt;strong>Overlay 网络&lt;/strong> 正常调度并连接到 &lt;strong>子节点（Worker）&lt;/strong> 上的容器。本教程将通过部署一个跨节点的测试应用，验证网络数据平面（Data Plane）是否畅通。&lt;/p>
&lt;p>&lt;strong>一、核心概念：为什么不能用“默认”网络？&lt;/strong>&lt;/p>
&lt;p>很多教程提到“不要使用默认网络”，这通常指两点：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>禁止使用 &lt;code>bridge&lt;/code> 网络&lt;/strong>：这是单机网络。如果你不指定网络，Docker 默认使用 &lt;code>bridge&lt;/code>，跨服务器的容器将无法互相访问。&lt;/li>
&lt;li>&lt;strong>必须使用 &lt;code>Overlay&lt;/code> 网络&lt;/strong>：Swarm 模式下，只有 Overlay 网络能建立跨物理机的虚拟隧道。&lt;/li>
&lt;li>&lt;strong>Dokploy 的做法&lt;/strong>：Dokploy 已经预设了一个名为 &lt;code>dokploy-network&lt;/code> 的 Overlay 网络。&lt;strong>我们的应用必须挂载到这个网络上&lt;/strong>，才能被 Dokploy 的 Traefik 网关识别并实现跨节点转发。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>二、准备工作&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>确保在 Dokploy 的 &lt;strong>Servers&lt;/strong> 菜单中，子节点显示为 &lt;code>Ready&lt;/code>。&lt;/li>
&lt;li>（可选）为子节点添加标签：
&lt;ul>
&lt;li>在管理节点终端执行：&lt;code>docker node update --label-add type=worker &amp;lt;子节点主机名&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;em>这能确保我们的测试应用准确落在子节点上。&lt;/em>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>三、编写部署文件 (Compose)&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 中新建一个 &lt;strong>Compose&lt;/strong>，选择 &lt;strong>Stack&lt;/strong> 模式，填入以下配置：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.8&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 服务 A：强制运行在管理节点 (Manager)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test-manager&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginxdemos/hello:plain-text&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicas&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">placement&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">constraints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">node.role == manager&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 服务 B：强制运行在子节点 (Worker)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test-worker&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginxdemos/hello:plain-text&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dokploy-network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicas&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">placement&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">constraints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 如果没打标签，可用 - node.role == worker&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">node.role == worker &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 使用 Dokploy 预设的 Overlay 网络&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">dokploy-network&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">external&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;em>注意：上述 YAML 中的注释行已保留，但请确保在实际编辑时不要误删关键配置。&lt;/em>&lt;/p>
&lt;p>&lt;strong>四、部署步骤&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>创建 Stack&lt;/strong>：在 Dokploy 项目中点击 &lt;code>Create Service&lt;/code> -&amp;gt; &lt;code>Compose&lt;/code>。&lt;/li>
&lt;li>&lt;strong>配置&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>Name&lt;/strong>: &lt;code>swarm-test&lt;/code>&lt;/li>
&lt;li>&lt;strong>Source&lt;/strong>: 直接粘贴上述 YAML 代码。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>部署&lt;/strong>：点击 &lt;strong>Deploy&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>确认位置&lt;/strong>：
&lt;ul>
&lt;li>部署完成后，在 Dokploy 的容器列表里查看。&lt;/li>
&lt;li>确认 &lt;code>test-manager&lt;/code> 运行在管理节点 IP 上。&lt;/li>
&lt;li>确认 &lt;code>test-worker&lt;/code> 运行在子节点 IP 上。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>五、联通性验证（手动测试）&lt;/strong>&lt;/p>
&lt;p>即使两个容器都显示 &amp;ldquo;Running&amp;rdquo;，也不代表网络是通的。我们需要执行以下两项压力测试：&lt;/p>
&lt;p>&lt;strong>1. 容器间内网互访（验证 Overlay 网络）&lt;/strong>&lt;/p>
&lt;p>进入管理节点上的 &lt;code>test-manager&lt;/code> 容器，尝试访问子节点上的服务名：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 在管理节点终端找到容器 ID&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker ps &lt;span class="p">|&lt;/span> grep test-manager
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 进入容器内部&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> -it &amp;lt;容器 ID&amp;gt; sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. 通过服务名访问子节点的容器（Swarm 会自动做 VIP 负载均衡）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://test-worker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>成功标志&lt;/strong>：如果返回 &lt;code>Server address: 10.0.x.x&lt;/code> 且该 IP 是子节点的内部 IP，说明 &lt;strong>Overlay 网络跨机通信正常&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. 外部网关转发（验证 Traefik 联通）&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 中为 &lt;code>test-worker&lt;/code> 服务配置一个域名（Domain）：&lt;/p>
&lt;ol>
&lt;li>在 &lt;code>test-worker&lt;/code> 的域名设置里绑定一个测试域名。&lt;/li>
&lt;li>通过浏览器访问该域名。&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>&lt;strong>原理&lt;/strong>：流量会先到达 &lt;strong>管理节点的 Traefik&lt;/strong> -&amp;gt; 通过 &lt;strong>dokploy-network&lt;/strong> -&amp;gt; 转发到 &lt;strong>子节点的容器&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>成功标志&lt;/strong>：浏览器正常显示网页。如果出现 &lt;code>502 Bad Gateway&lt;/code>，说明管理节点和子节点之间的 &lt;strong>4789/UDP&lt;/strong> 端口被防火墙拦截了。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>六、故障排查&lt;/strong>&lt;/p>
&lt;p>如果测试不通，请检查各节点间防火墙是否放行了以下 Swarm 必需端口：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>TCP 2377&lt;/strong>：集群管理通信。&lt;/li>
&lt;li>&lt;strong>TCP/UDP 7946&lt;/strong>：节点发现与健康检查。&lt;/li>
&lt;li>&lt;strong>UDP 4789&lt;/strong>：&lt;strong>关键！&lt;/strong> 数据平面 Overlay 网络（UDP 封装）。如果该端口不通，容器能启动但无法互相 ping 通。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>检查指令（在任一节点查看网络详情）：&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker network inspect dokploy-network
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>确认子节点（Worker）的容器 IP 是否出现在 &lt;code>Containers&lt;/code> 列表中。&lt;/p>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;p>在 Dokploy 中测试子节点，&lt;strong>核心就是利用 &lt;code>dokploy-network&lt;/code> (External Overlay)&lt;/strong>。只要能通过管理节点的容器 &lt;code>curl&lt;/code> 通子节点的容器名，你的集群网络就是完美的。&lt;/p>
&lt;h2 id="dokploy--docker-swarm-实战为什么扩容后看不见容器多节点部署避坑指南">Dokploy + Docker Swarm 实战：为什么扩容后看不见容器？(多节点部署避坑指南)
&lt;/h2>&lt;p>&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-5.png"
width="1912"
height="954"
srcset="https://www.zata.cc/p/dokploy/images/index/image-5_hu7863231414691180608.png 480w, https://www.zata.cc/p/dokploy/images/index/image-5_hu5255400510229230479.png 1024w"
loading="lazy"
alt="dokploy只能看见本地的容器,但是实际上是有两个容器在跑的"
class="gallery-image"
data-flex-grow="200"
data-flex-basis="481px"
>&lt;/p>
&lt;p>最近在使用 &lt;strong>Dokploy&lt;/strong> 配合 &lt;strong>Docker Swarm&lt;/strong> 进行多节点部署时，遇到了一些非常经典的概念误区。这篇笔记旨在记录从单机迈向集群模式时，容易让人产生“自我怀疑”的几个瞬间，以及如何正确地管理你的 Swarm 集群。&lt;/p>
&lt;p>&lt;strong>01. 现象：明明扩容了，容器去哪了？&lt;/strong>&lt;/p>
&lt;p>我在 Dokploy 的后台将一个应用（&lt;code>transfileserver&lt;/code>）的副本数（Replicas）设置为了 &lt;strong>2&lt;/strong>。&lt;/p>
&lt;p>在主节点（Master/Manager）终端输入 &lt;code>docker service ls&lt;/code>，状态看起来非常完美：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">root@master:~# docker service ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ID NAME REPLICAS IMAGE
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">j4pif4la2ox3 smallappforfun-test..._app 2/2 registry.../app:latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>REPLICAS 2/2&lt;/code> 告诉我：期望跑 2 个，实际跑了 2 个。一切正常，对吧？&lt;/p>
&lt;p>&lt;strong>但是&lt;/strong>，当我习惯性地在主节点输入 &lt;code>docker ps&lt;/code> 想看看这两个容器时，却发现：&lt;strong>只有一个容器在运行！&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">root@master:~# docker ps &lt;span class="p">|&lt;/span> grep transfileserver
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// 只有一行输出，显示其中一个容器 ID
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>我的第一个反应是：&lt;/strong> 部署失败了？还是 Dokploy UI 显示 bug 了？为什么丢了一个容器？&lt;/p>
&lt;p>&lt;strong>02. 原理：上帝视角 vs. 本地视角&lt;/strong>&lt;/p>
&lt;p>其实，部署并没有失败。这是 &lt;strong>Docker Swarm&lt;/strong> 最基本的运行逻辑，也是新手最容易混淆的地方。&lt;/p>
&lt;p>&lt;strong>为什么 &lt;code>docker ps&lt;/code> 看不到？&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>docker ps&lt;/code> 是“本地视角”&lt;/strong>：这个命令问的是当前这台物理服务器：“你的 CPU 和内存里现在跑着哪些进程？”&lt;/li>
&lt;li>&lt;strong>Swarm 调度机制&lt;/strong>：当你设置 &lt;code>replicas: 2&lt;/code> 且拥有多个节点时，Swarm 调度器为了负载均衡，大概率会将其中一个容器分配给主节点，另一个分配给子节点（Worker Node）。&lt;/li>
&lt;/ul>
&lt;p>所以，你在主节点运行 &lt;code>docker ps&lt;/code>，当然只能看到分配给主节点的那个容器。另一个容器正在子节点的肚子里跑得欢呢。&lt;/p>
&lt;p>&lt;strong>正确的查看方式：上帝视角&lt;/strong>&lt;/p>
&lt;p>要确认所有副本的状态和位置，不能用 &lt;code>docker ps&lt;/code>，而要用 &lt;strong>Service&lt;/strong> 级别的命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker service ps &amp;lt;你的服务名称&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出结果会像这样：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">ID&lt;/th>
&lt;th style="text-align: left">NAME&lt;/th>
&lt;th style="text-align: left">NODE&lt;/th>
&lt;th style="text-align: left">DESIRED STATE&lt;/th>
&lt;th style="text-align: left">CURRENT STATE&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">x7&amp;hellip;&lt;/td>
&lt;td style="text-align: left">&amp;hellip;app.1&lt;/td>
&lt;td style="text-align: left">&lt;strong>racknerd-master&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Running&lt;/td>
&lt;td style="text-align: left">Running&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">y9&amp;hellip;&lt;/td>
&lt;td style="text-align: left">&amp;hellip;app.2&lt;/td>
&lt;td style="text-align: left">&lt;strong>worker-node-01&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Running&lt;/td>
&lt;td style="text-align: left">Running&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>注意 &lt;strong>NODE&lt;/strong> 这一列。你可以清晰地看到，Swarm 已经把任务分发到了不同的机器上。这证明你的负载均衡集群已经完美工作了。&lt;/p>
&lt;p>&lt;strong>03. 疑问：子节点需要安装 Dokploy 吗？&lt;/strong>&lt;/p>
&lt;p>既然应用跑在子节点上，我是否需要在子节点上也跑一遍 Dokploy 的安装脚本？&lt;/p>
&lt;p>&lt;strong>答案是：绝对不需要，千万别装！&lt;/strong>&lt;/p>
&lt;p>&lt;strong>为什么？&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>架构逻辑&lt;/strong>：Dokploy 是“指挥官”（Brain），它只需要存在于主节点。Worker 节点只需要安装基础的 Docker Engine。主节点通过 Swarm 协议遥控子节点干活。&lt;/li>
&lt;li>&lt;strong>端口冲突&lt;/strong>：Dokploy 自带 Traefik（网关），占用 80/443 端口。如果在子节点再装一套，会导致端口冲突，破坏集群的统一路由网络。&lt;/li>
&lt;li>&lt;strong>资源浪费&lt;/strong>：子节点会被迫运行一套多余的 Postgres、Redis 和监控服务。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>子节点只需要做一件事&lt;/strong>：安装 Docker，然后运行 &lt;code>docker swarm join ...&lt;/code> 命令加入集群即可。&lt;/p>
&lt;p>&lt;strong>04. 关键避坑：多节点下的文件存储（Volumes）&lt;/strong>&lt;/p>
&lt;p>虽然多节点部署成功了，但如果你的应用涉及到文件上传或持久化存储（比如我的文件传输服务），这里有一个巨大的隐患。&lt;/p>
&lt;p>&lt;strong>场景重现&lt;/strong>&lt;/p>
&lt;p>假设你的 &lt;code>docker-compose.yml&lt;/code> 是这样写的：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./uploads:/app/uploads&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>用户 A&lt;/strong> 上传文件，请求被分发到了 &lt;strong>主节点&lt;/strong> 的容器。文件保存在主节点的硬盘里。&lt;/li>
&lt;li>&lt;strong>用户 A&lt;/strong> 再次刷新，请求被分发到了 &lt;strong>子节点&lt;/strong> 的容器。&lt;/li>
&lt;li>&lt;strong>结果&lt;/strong>：子节点容器里是空的！用户发现刚传的文件“丢了”。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>解决方案&lt;/strong>&lt;/p>
&lt;p>在 Swarm 模式下，本地目录挂载（Bind Mounts）不再适用于需要数据共享的场景。你需要：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>方案一（推荐）：对象存储&lt;/strong>
修改代码，不要把文件存本地硬盘，而是存到 AWS S3、阿里云 OSS 或自建的 MinIO 中。这是云原生应用的最佳实践。&lt;/li>
&lt;li>&lt;strong>方案二：NFS（网络文件系统）&lt;/strong>
搭建一个 NFS 服务器，让所有节点挂载同一个网络硬盘。&lt;/li>
&lt;li>&lt;strong>方案三：限制节点（临时方案）&lt;/strong>
如果是单机应用强行上 Swarm，可以通过配置 &lt;code>placement constraints&lt;/code>，强制该服务只运行在主节点上，放弃多节点负载均衡，只利用 Swarm 的管理功能。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>信任 &lt;code>docker service ls&lt;/code>&lt;/strong>：如果它显示 &lt;code>2/2&lt;/code>，那就是成功的。&lt;/li>
&lt;li>&lt;strong>用对命令&lt;/strong>：查看集群状态用 &lt;code>docker service ps&lt;/code>，而不是 &lt;code>docker ps&lt;/code>。&lt;/li>
&lt;li>&lt;strong>保持子节点纯净&lt;/strong>：不要在 Worker 节点重复安装 Dokploy。&lt;/li>
&lt;li>&lt;strong>留意存储&lt;/strong>：多节点部署必须解决文件共享问题，否则数据会“漂移”。&lt;/li>
&lt;/ol>
&lt;p>希望这篇避坑指南能帮你更自信地驾驭 Dokploy 和 Docker Swarm！&lt;/p>
&lt;h2 id="dokploy-安全建议检查与服务器加固操作指南">Dokploy 安全建议检查与服务器加固操作指南
&lt;/h2>&lt;p>&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-3.png"
width="3404"
height="1932"
srcset="https://www.zata.cc/p/dokploy/images/index/image-3_hu10136642107161284263.png 480w, https://www.zata.cc/p/dokploy/images/index/image-3_hu7800812264568771261.png 1024w"
loading="lazy"
alt="刚安装完成的dokploy"
class="gallery-image"
data-flex-grow="176"
data-flex-basis="422px"
>&lt;/p>
&lt;p>这张截图显示的是 Dokploy 的 &lt;strong>安全建议检查（Security Suggestions）&lt;/strong>。它并不是让你在 Dokploy 的网页界面里填个表，而是提示你需要登录到 &lt;strong>服务器的终端（Terminal）&lt;/strong> 去修改系统配置文件。这是一份服务器“加固”清单。要把这些红色的叉号（❌）变成绿色的勾号（✅），你需要 SSH 登录到这台服务器，依次执行以下操作。&lt;/p>
&lt;p>⚠️ &lt;strong>警告：在操作之前，请务必确保你已经可以通过 SSH 密钥登录服务器！如果你在没有配置好密钥的情况下禁用了密码登录，你将无法进入服务器！&lt;/strong>&lt;/p>
&lt;hr>
&lt;p>&lt;strong>第一步：修复 SSH 设置 (最重要)&lt;/strong>&lt;/p>
&lt;p>截图建议你禁用密码登录（Password Auth）和 PAM，只允许密钥登录。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>SSH 登录服务器&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>编辑 SSH 配置文件&lt;/strong>：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo nano /etc/ssh/sshd_config
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>修改以下配置项&lt;/strong>（使用键盘上下键找到这些行，修改后的样子如下）：
&lt;ul>
&lt;li>找到 &lt;code>PasswordAuthentication&lt;/code>，将其改为 &lt;code>no&lt;/code>：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">PasswordAuthentication no
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>找到 &lt;code>UsePAM&lt;/code>，建议改为 &lt;code>no&lt;/code> (注意：有些系统改为 no 可能会有副作用，通常改 PasswordAuthentication 最关键，但为了满足 Dokploy 的检查，你可以改为 no)：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">UsePAM no
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;em>确保 &lt;code>PubkeyAuthentication&lt;/code> 是 &lt;code>yes&lt;/code>（通常默认就是）。&lt;/em>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>保存并退出&lt;/strong>：按 &lt;code>Ctrl + O&lt;/code> 回车保存，按 &lt;code>Ctrl + X&lt;/code> 退出。&lt;/li>
&lt;li>&lt;strong>重启 SSH 服务&lt;/strong>使配置生效：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo systemctl restart ssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;em>操作完这一步，SSH 部分的红色叉号应该会变绿。&lt;/em>&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>第二步：配置 UFW 防火墙&lt;/strong>&lt;/p>
&lt;p>截图显示 UFW 已安装但未激活，且默认策略不是“拒绝”。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>设置默认拒绝进入&lt;/strong>（安全基线）：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo ufw default deny incoming
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>放行必要的端口&lt;/strong>（&lt;strong>非常重要，否则你会把自己关在外面&lt;/strong>）：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 放行 SSH (通常是 22)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ufw allow 22/tcp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 放行 Web 服务 (HTTP/HTTPS)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ufw allow 80/tcp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ufw allow 443/tcp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 放行 Dokploy 面板端口 (默认是 3000)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ufw allow 3000/tcp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>启用防火墙&lt;/strong>：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo ufw &lt;span class="nb">enable&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;em>(系统会提示你这可能会断开 SSH 连接，输入 &lt;code>y&lt;/code> 确认即可，只要上面 allow 22 执行了就没事)&lt;/em>。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>第三步：安装并配置 Fail2Ban&lt;/strong>&lt;/p>
&lt;p>截图显示 Fail2Ban 根本没安装，建议安装并开启 SSH 攻击保护（Aggressive 模式）。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>安装 Fail2Ban&lt;/strong>：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo apt-get update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt-get install fail2ban -y
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>创建配置文件&lt;/strong>（不要直接改 jail.conf，新建 jail.local）：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo nano /etc/fail2ban/jail.local
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>粘贴以下内容&lt;/strong>（开启 SSH 保护并设为激进模式）：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[sshd]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">enabled&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">port&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">ssh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">sshd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">logpath&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">/var/log/auth.log&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">maxretry&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 截图建议 SSH Mode: aggressive&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">aggressive&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>保存并退出&lt;/strong>：&lt;code>Ctrl + O&lt;/code> 回车，&lt;code>Ctrl + X&lt;/code>。&lt;/li>
&lt;li>&lt;strong>启动 Fail2Ban 服务&lt;/strong>：
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> fail2ban
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl start fail2ban
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>最后一步：验证&lt;/strong>&lt;/p>
&lt;p>回到 Dokploy 网页界面，点击弹窗右上角的 &lt;strong>Refresh (刷新)&lt;/strong> 按钮。如果操作正确，大部分或者全部的红叉 ❌ 应该都会变成绿色的 ✅。&lt;/p>
&lt;p>&lt;strong>简单总结：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>改 &lt;code>/etc/ssh/sshd_config&lt;/code> 禁止密码。&lt;/li>
&lt;li>运行 &lt;code>ufw&lt;/code> 命令开放端口并开启防火墙。&lt;/li>
&lt;li>运行 &lt;code>apt install fail2ban&lt;/code> 并配置它。&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://www.zata.cc/p/dokploy/images/index/image-4.png"
width="3404"
height="1932"
srcset="https://www.zata.cc/p/dokploy/images/index/image-4_hu15573905085076454083.png 480w, https://www.zata.cc/p/dokploy/images/index/image-4_hu11951157610726082232.png 1024w"
loading="lazy"
alt="配置完成如下"
class="gallery-image"
data-flex-grow="176"
data-flex-basis="422px"
>&lt;/p>
&lt;h2 id="dokploy-搭配-nginx-proxy-manager-保姆级实操教程">Dokploy 搭配 Nginx Proxy Manager 保姆级实操教程
&lt;/h2>&lt;p>没问题！既然你习惯了 1Panel 的操作逻辑，那么&lt;strong>方案一：使用 Nginx Proxy Manager (NPM)&lt;/strong> 绝对是你的最佳选择。&lt;/p>
&lt;p>这将是一个&lt;strong>手把手、保姆级&lt;/strong>的实操教程，涵盖从网络配置到最终通过域名访问的全过程。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>准备工作&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>一台安装好 Dokploy 的服务器&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>一个域名&lt;/strong>（假设为 &lt;code>example.com&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>确保端口未被占用&lt;/strong>：确保服务器的 80 和 443 端口没有被其他程序占用（Dokploy 面板默认通常在 3000 端口，所以 80/443 通常是空闲的）。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>第一步：规划 Docker 网络（关键点）&lt;/strong>&lt;/p>
&lt;p>在 1Panel 里，系统帮你自动处理了网络。但在 Dokploy（以及原生 Docker）中，为了让“反向代理容器”能找到“应用容器”，它们必须在&lt;strong>同一个 Docker 网络&lt;/strong>中。&lt;/p>
&lt;p>我们先创建一个专用的网络，名字叫 &lt;code>proxy-net&lt;/code>。&lt;/p>
&lt;ol>
&lt;li>登录你的服务器终端（SSH）。&lt;/li>
&lt;li>执行以下命令创建网络：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker network create proxy-net
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这一步做完，以后所有的应用和 NPM 都加入这个网络，它们就能通过“容器名”互相通信了。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>第二步：在 Dokploy 中部署 Nginx Proxy Manager&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>登录 Dokploy 面板。&lt;/li>
&lt;li>进入 &lt;strong>Project（项目）&lt;/strong> -&amp;gt; 选择或新建一个项目（例如叫 &lt;code>System&lt;/code>）。&lt;/li>
&lt;li>点击 &lt;strong>Compose&lt;/strong> -&amp;gt; &lt;strong>Add Compose&lt;/strong>。
&lt;ul>
&lt;li>&lt;strong>Name:&lt;/strong> &lt;code>nginx-proxy-manager&lt;/code>&lt;/li>
&lt;li>&lt;strong>Description:&lt;/strong> 反向代理服务&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>在右侧的编辑器中，粘贴以下配置（注意我添加了网络配置）：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.8&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">app&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;jc21/nginx-proxy-manager:latest&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nginx-proxy-manager&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;80:80&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;81:81&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;443:443&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./data:/data&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./letsencrypt:/etc/letsencrypt&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">proxy-net&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">proxy-net&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">external&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="5">
&lt;li>点击 &lt;strong>Deploy&lt;/strong>（部署）。&lt;/li>
&lt;li>等待日志显示 &lt;code>Listening on port 81&lt;/code>，表示启动成功。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>第三步：初始化 Nginx Proxy Manager&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>在浏览器访问：&lt;code>http://你的服务器 IP:81&lt;/code>&lt;/li>
&lt;li>使用默认账号登录：
&lt;ul>
&lt;li>&lt;strong>Email:&lt;/strong> &lt;code>admin@example.com&lt;/code>&lt;/li>
&lt;li>&lt;strong>Password:&lt;/strong> &lt;code>changeme&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>登录后，系统会立即要求你修改&lt;strong>用户名&lt;/strong>和&lt;strong>密码&lt;/strong>，请务必修改并记住。&lt;/li>
&lt;/ol>
&lt;p>此时，你的“反向代理中心”已经搭建好了！&lt;/p>
&lt;hr>
&lt;p>&lt;strong>第四步：部署一个业务应用（以 Alist 为例）&lt;/strong>&lt;/p>
&lt;p>现在我们来部署一个实际的应用，并尝试通过域名访问它。&lt;/p>
&lt;ol>
&lt;li>回到 Dokploy 面板。&lt;/li>
&lt;li>进入你的项目，点击 &lt;strong>Compose&lt;/strong> -&amp;gt; &lt;strong>Add Compose&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>Name:&lt;/strong> &lt;code>alist&lt;/code>&lt;/li>
&lt;li>粘贴以下配置（&lt;strong>注意看 &lt;code>networks&lt;/code> 和 &lt;code>ports&lt;/code> 的部分&lt;/strong>）：&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.3&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">alist&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;xhofe/alist:latest&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">alist-app&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">always&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;./etc/alist:/opt/alist/data&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">proxy-net&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">proxy-net&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">external&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="5">
&lt;li>点击 &lt;strong>Deploy&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>重点理解&lt;/strong>：此时，&lt;code>alist-app&lt;/code> 和 &lt;code>nginx-proxy-manager&lt;/code> 都在 &lt;code>proxy-net&lt;/code> 这个网络里。虽然你在公网通过 IP:5244 访问不到 Alist（因为没暴露端口），但 NPM 可以通过内部网络访问到它。&lt;/p>
&lt;hr>
&lt;p>&lt;strong>第五步：域名解析 (DNS)&lt;/strong>&lt;/p>
&lt;p>去你的域名服务商（阿里云、腾讯云、Cloudflare 等）：&lt;/p>
&lt;ol>
&lt;li>添加一条 &lt;strong>A 记录&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>主机记录 (Name):&lt;/strong> 例如 &lt;code>pan&lt;/code> (即 &lt;code>pan.example.com&lt;/code>)。&lt;/li>
&lt;li>&lt;strong>记录值 (Value):&lt;/strong> 填写你 &lt;strong>Dokploy 服务器的公网 IP&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>第六步：在 NPM 中配置反向代理（最后一步！）&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>回到 NPM 的管理后台 (&lt;code>http://你的服务器 IP:81&lt;/code>)。&lt;/li>
&lt;li>点击顶部菜单 &lt;strong>Hosts&lt;/strong> -&amp;gt; &lt;strong>Proxy Hosts&lt;/strong>。&lt;/li>
&lt;li>点击右上角 &lt;strong>Add Proxy Host&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>A. Details 标签页 (基本信息)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Domain Names:&lt;/strong> &lt;code>pan.example.com&lt;/code> (你刚才解析的域名)&lt;/li>
&lt;li>&lt;strong>Scheme:&lt;/strong> &lt;code>http&lt;/code>&lt;/li>
&lt;li>&lt;strong>Forward Hostname / IP:&lt;/strong> &lt;code>alist-app&lt;/code>
&lt;ul>
&lt;li>这里最关键！填写你在第四步定义的 &lt;code>container_name&lt;/code>。不要填 IP，填容器名即可。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Forward Port:&lt;/strong> &lt;code>5244&lt;/code>
&lt;ul>
&lt;li>填写 Alist 的内部端口。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Cache Assets / Block Common Exploits:&lt;/strong> 推荐勾选。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>B. SSL 标签页 (HTTPS 证书)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>SSL Certificate:&lt;/strong> 选择 &lt;code>Request a new SSL Certificate&lt;/code>。&lt;/li>
&lt;li>&lt;strong>Force SSL:&lt;/strong> 勾选 (强制跳转 HTTPS)。&lt;/li>
&lt;li>&lt;strong>HTTP/2 Support:&lt;/strong> 推荐勾选。&lt;/li>
&lt;li>&lt;strong>Email Address:&lt;/strong> 填写你的邮箱。&lt;/li>
&lt;li>&lt;strong>I Agree to the Terms:&lt;/strong> 勾选。&lt;/li>
&lt;/ul>
&lt;ol start="4">
&lt;li>点击 &lt;strong>Save&lt;/strong>。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>验证成果&lt;/strong>&lt;/p>
&lt;p>现在，在浏览器输入 &lt;code>https://pan.example.com&lt;/code>。&lt;/p>
&lt;ul>
&lt;li>如果一切顺利，你应该能看到 Alist 的页面。&lt;/li>
&lt;li>并且浏览器地址栏有一把&lt;strong>小锁&lt;/strong>（HTTPS 已启用）。&lt;/li>
&lt;li>整个过程你不需要手动去碰 Nginx 的配置文件，也不需要手动上传证书。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>进阶小贴士&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>后续添加新应用：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>在 Dokploy 部署新应用时，记得在 Compose 文件里加上 &lt;code>networks: - proxy-net&lt;/code>。&lt;/li>
&lt;li>记下容器名 (&lt;code>container_name&lt;/code>) 和内部端口。&lt;/li>
&lt;li>去 NPM 添加一条新的 Proxy Host 即可。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>关于端口 81 的安全：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>NPM 的后台（81 端口）直接暴露在公网其实不太安全。&lt;/li>
&lt;li>&lt;strong>高级玩法&lt;/strong>：你可以在 NPM 里，把自己（&lt;code>nginx-proxy-manager&lt;/code> 容器，端口 81）也代理一下！&lt;/li>
&lt;li>配置一个域名如 &lt;code>npm.example.com&lt;/code> -&amp;gt; Forward Hostname: &lt;code>nginx-proxy-manager&lt;/code> -&amp;gt; Port: &lt;code>81&lt;/code>。&lt;/li>
&lt;li>一旦配置成功，去云服务商防火墙把 81 端口封掉，只留 80/443，以后通过 &lt;code>npm.example.com&lt;/code> 访问管理后台，更加安全且带有 HTTPS。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>通过这套流程，你在 Dokploy 上就完美复刻了 1Panel 的反向代理体验，甚至在多服务器扩展性上比 1Panel 更强（因为基于标准的 Docker 网络）。&lt;/p>
&lt;h1 id="dokploy介绍">Dokploy介绍
&lt;/h1>&lt;p>Dokploy 是一个新兴的、开源的、基于 Web 的服务器管理和应用程序部署平台，旨在让开发者和中小型团队能够像使用 Heroku 或 Vercel 一样简便地部署和管理应用，但所有服务完全运行在您自己拥有或控制的服务器（如 VPS）上。简单来说，Dokploy 是“自托管/私有化部署的 Heroku”。&lt;/p>
&lt;p>它通过一个直观的 Web 控制面板，将复杂的 Docker、Git、Webhook 和反向代理配置过程完全可视化，让您无需记忆冗长的命令行指令，就能完成应用部署、数据库创建、SSL 证书安装等一系列操作。&lt;/p>
&lt;p>核心特性&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>基于 Docker&lt;/strong>：所有应用和服务都以 Docker 容器形式运行，保证环境的一致性和隔离性。支持上传标准的 &lt;code>docker-compose.yml&lt;/code> 文件，或使用内置模板快速创建多容器应用。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>可视化部署&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Git 集成&lt;/strong>：连接 GitHub、GitLab 或 Bitbucket 仓库，实现持续部署。每次推送代码到指定分支，Dokploy 会自动拉取、构建并重新部署应用。&lt;/li>
&lt;li>&lt;strong>Docker 镜像部署&lt;/strong>：可直接从 Docker Hub 或私有仓库拉取镜像进行部署。&lt;/li>
&lt;li>&lt;strong>环境变量管理&lt;/strong>：在网页界面中轻松添加、编辑和管理敏感配置信息，无需手动编辑文件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>内置服务支持&lt;/strong>：一键部署常用数据库（MySQL、PostgreSQL、MongoDB、Redis 等）、缓存服务和反向代理（Nginx），无需手动编写配置文件。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>SSL 证书自动管理&lt;/strong>：集成 Let’s Encrypt，为您的应用域名自动签发和续期免费的 HTTPS 证书，仅需点击几下即可完成配置。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>直观的监控与管理&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>实时查看容器状态（运行/停止）、CPU 与内存使用情况。&lt;/li>
&lt;li>查看实时日志流，支持在线启动、停止、重启容器。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>多服务器管理&lt;/strong>：一个 Dokploy 控制面板可同时管理多个远程服务器（节点），便于在不同机器上分布和调度应用。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>开源与可扩展&lt;/strong>：完全开源（采用商业源码许可证），代码透明，社区驱动，支持通过插件或模板扩展功能，便于二次开发与定制。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>典型工作流程&lt;/p>
&lt;ol>
&lt;li>&lt;strong>准备一台 VPS&lt;/strong>：在 DigitalOcean、Linode、阿里云、腾讯云等服务商购买一台安装了 Ubuntu 或 Debian 的虚拟服务器。&lt;/li>
&lt;li>&lt;strong>安装 Dokploy&lt;/strong>：使用官方提供的一键安装脚本，在服务器上部署 Dokploy（其本身也是一个 Docker 容器）。&lt;/li>
&lt;li>&lt;strong>访问控制面板&lt;/strong>：通过浏览器访问服务器 IP 和指定端口，进入 Dokploy 的 Web 界面并完成初始设置。&lt;/li>
&lt;li>&lt;strong>连接 Git 账户&lt;/strong>：在面板中授权您的 GitHub、GitLab 或 Bitbucket 账号。&lt;/li>
&lt;li>&lt;strong>创建新项目&lt;/strong>：点击“部署应用”，选择目标仓库和分支。&lt;/li>
&lt;li>&lt;strong>配置部署参数&lt;/strong>：设置端口映射、环境变量、构建命令等。Dokploy 会自动生成 &lt;code>Dockerfile&lt;/code>（如项目未提供），或使用您上传的 &lt;code>docker-compose.yml&lt;/code>。&lt;/li>
&lt;li>&lt;strong>执行部署&lt;/strong>：点击“部署”按钮，Dokploy 会自动拉取代码、构建镜像、启动容器，并通过内置的 Traefik 或 Nginx 配置好域名访问。&lt;/li>
&lt;li>&lt;strong>持续管理&lt;/strong>：部署完成后，通过面板监控应用状态、查看日志、添加自定义域名并启用 SSL。&lt;/li>
&lt;/ol>
&lt;p>适合谁使用？&lt;/p>
&lt;ul>
&lt;li>&lt;strong>前端/全栈开发者&lt;/strong>：希望快速部署 Next.js、Nuxt.js、React、Vue 或 Node.js 等项目，却不愿花时间处理服务器运维。&lt;/li>
&lt;li>&lt;strong>初创团队和小公司&lt;/strong>：需要成本可控、易于维护的部署方案，同时避免被 Heroku、Railway 等 PaaS 平台绑定或高额费用困扰。&lt;/li>
&lt;li>&lt;strong>注重数据隐私的个人或组织&lt;/strong>：因合规性、安全或数据主权要求，必须将应用部署在自有基础设施上，但仍希望享受现代云平台的便捷体验。&lt;/li>
&lt;li>&lt;strong>Docker 初学者&lt;/strong>：想体验容器化部署的优势，但对命令行、网络配置、存储卷等概念感到困难。&lt;/li>
&lt;/ul>
&lt;p>优点与缺点&lt;/p>
&lt;p>&lt;strong>优点：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>成本效益高&lt;/strong>：仅需支付 VPS 费用，Dokploy 本身免费，长期使用远低于按需付费的云 PaaS。&lt;/li>
&lt;li>&lt;strong>完全自主可控&lt;/strong>：数据和基础设施由您掌控，可自由定制服务器配置和安全策略。&lt;/li>
&lt;li>&lt;strong>开发者体验友好&lt;/strong>：极大降低了 Docker 和 CI/CD 的入门门槛，部署流程流畅直观。&lt;/li>
&lt;li>&lt;strong>活跃社区&lt;/strong>：项目更新频繁，功能持续迭代，社区支持逐步增强。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>缺点：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>依赖自有服务器&lt;/strong>：您需具备基本的服务器运维能力（如 SSH 登录、防火墙设置），并自行负责安全更新、备份和底层维护。&lt;/li>
&lt;li>&lt;strong>非企业级架构&lt;/strong>：相比 Kubernetes 或商业面板（如 Plesk、cPanel），在集群管理、高可用、自动伸缩等方面功能尚不完善。&lt;/li>
&lt;li>&lt;strong>新兴项目&lt;/strong>：作为较新的开源工具，其长期稳定性、大规模生产环境验证和生态成熟度仍需时间检验。&lt;/li>
&lt;/ul>
&lt;p>与其他工具的对比&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">工具&lt;/th>
&lt;th style="text-align: left">类型&lt;/th>
&lt;th style="text-align: left">核心特点&lt;/th>
&lt;th style="text-align: left">适合场景&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>Dokploy&lt;/strong>&lt;/td>
&lt;td style="text-align: left">自托管 PaaS 面板&lt;/td>
&lt;td style="text-align: left">开源、可视化、Git 集成、轻量级、基于 Docker&lt;/td>
&lt;td style="text-align: left">个人开发者、小团队自托管应用&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>Heroku / Vercel&lt;/strong>&lt;/td>
&lt;td style="text-align: left">云 PaaS&lt;/td>
&lt;td style="text-align: left">极致简化、全托管、生态丰富、按需付费&lt;/td>
&lt;td style="text-align: left">追求效率、不愿管理服务器的用户&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>Portainer&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Docker 管理面板&lt;/td>
&lt;td style="text-align: left">通用型容器、镜像、网络、卷管理&lt;/td>
&lt;td style="text-align: left">需要精细管理 Docker 环境的管理员&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>Coolify / CapRover&lt;/strong>&lt;/td>
&lt;td style="text-align: left">自托管 PaaS 面板&lt;/td>
&lt;td style="text-align: left">与 Dokploy 定位高度重叠，功能相似&lt;/td>
&lt;td style="text-align: left">可作为 Dokploy 的替代选择进行对比&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>Kubernetes&lt;/strong>&lt;/td>
&lt;td style="text-align: left">容器编排平台&lt;/td>
&lt;td style="text-align: left">企业级、高扩展性、功能强大但复杂&lt;/td>
&lt;td style="text-align: left">大型系统、微服务架构、需要弹性伸缩的场景&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>如何开始？&lt;/p>
&lt;ol>
&lt;li>访问 Dokploy 官方网站获取最新文档和安装指南：&lt;a class="link" href="https://dokploy.com" target="_blank" rel="noopener"
>https://dokploy.com&lt;/a>&lt;/li>
&lt;li>查看开源代码和社区贡献：&lt;a class="link" href="https://github.com/Dokploy/dokploy" target="_blank" rel="noopener"
>https://github.com/Dokploy/dokploy&lt;/a>&lt;/li>
&lt;/ol>
&lt;p>总结&lt;/p>
&lt;p>Dokploy 填补了“完全托管的云服务”与“手动服务器运维”之间的空白，让开发者能专注于编写代码，而将部署与运维的复杂性封装在一个美观、易用的界面之后。对于追求自主权、控制权和成本效益的开发者而言，Dokploy 是一个极具吸引力的现代部署解决方案。如果您正在寻找一种比手动操作更高效、比大型云平台更自主的部署方式，Dokploy 绝对值得一试。&lt;/p></description></item><item><title>Coolify</title><link>https://www.zata.cc/p/coolify/</link><pubDate>Sat, 21 Feb 2026 17:19:21 +0800</pubDate><guid>https://www.zata.cc/p/coolify/</guid><description>&lt;img src="https://www.zata.cc/p/coolify/images/index/index.png" alt="Featured image of post Coolify" />&lt;h3 id="一-产品核心定位-product-positioning">一、 产品核心定位 (Product Positioning)
&lt;/h3>&lt;p>Coolify 是一款&lt;strong>开源、可自托管的 PaaS（平台即服务）系统&lt;/strong>。
如果用一句话来向投资人或技术团队推销它：&lt;strong>“它是架设在你自有服务器上的 Vercel、Heroku 或 Render，让你用云主机的底层成本，享受顶级云厂商的 DevOps 自动化体验。”&lt;/strong>&lt;/p>
&lt;p>&lt;strong>核心商业逻辑&lt;/strong>：解耦“软件体验”与“硬件基础设施”。它将底层服务器的计算资源池化，在上面套了一层极简的 UI 和自动化脚本。&lt;/p>
&lt;hr>
&lt;h3 id="二-核心功能矩阵-core-features">二、 核心功能矩阵 (Core Features)
&lt;/h3>&lt;p>Coolify 的功能设计紧紧围绕“研发交付生命周期”展开，极大地压缩了 Time-to-Market（上市时间）：&lt;/p>
&lt;h4 id="1-自动化应用部署-gitops--cicd">1. 自动化应用部署 (GitOps &amp;amp; CI/CD)
&lt;/h4>&lt;ul>
&lt;li>&lt;strong>代码即部署&lt;/strong>：深度集成 GitHub, GitLab, Bitbucket, Gitea。开发人员提交代码（git push）后，Coolify 自动拉取、构建并部署。&lt;/li>
&lt;li>&lt;strong>PR 预览环境&lt;/strong>：当提交 Pull Request 时，可自动生成一个带独立域名的临时预览环境，PR 合并后自动销毁，极大方便 QA 和产品验收。&lt;/li>
&lt;li>&lt;strong>多栈支持（Zero-Config）&lt;/strong>：无论是 Node.js, Python, Go, Rust 还是 PHP，通常不需要手写 Dockerfile，系统会自动识别语言并打包构建。&lt;/li>
&lt;/ul>
&lt;h4 id="2-数据库与存储管理-database-as-a-service">2. 数据库与存储管理 (Database as a Service)
&lt;/h4>&lt;ul>
&lt;li>&lt;strong>一键拉起&lt;/strong>：支持一键部署 PostgreSQL, MySQL, MariaDB, MongoDB, Redis 等主流数据库。&lt;/li>
&lt;li>&lt;strong>自动备份&lt;/strong>：内置备份策略，可配置 Cron 任务，将数据库自动备份至本地或兼容 S3 的云存储（如 AWS S3, Cloudflare R2），解决数据灾备问题。&lt;/li>
&lt;/ul>
&lt;h4 id="3-服务模板市场-1-click-services">3. 服务模板市场 (1-Click Services)
&lt;/h4>&lt;ul>
&lt;li>&lt;strong>内置应用商店&lt;/strong>：内置了上百种热门开源软件模板（如 WordPress, Ghost, Supabase, MinIO, Metabase 等）。产品或运营团队可绕过开发，一键部署所需工具。&lt;/li>
&lt;/ul>
&lt;h4 id="4-基础设施与网络自动化-infra--networking">4. 基础设施与网络自动化 (Infra &amp;amp; Networking)
&lt;/h4>&lt;ul>
&lt;li>&lt;strong>多机管理 (BYOS)&lt;/strong>：支持“自带服务器”。可以在一台主控机上，通过 SSH 挂载管理位于阿里云、AWS 甚至家里的多台不同节点的服务器。&lt;/li>
&lt;li>&lt;strong>智能网关与 SSL&lt;/strong>：自动配置反向代理（Traefik 或 Caddy），全自动申请和续期 Let&amp;rsquo;s Encrypt 的 HTTPS 证书，无需手动改 Nginx 配置。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h3 id="三-底层技术架构-technical-underpinnings">三、 底层技术架构 (Technical Underpinnings)
&lt;/h3>&lt;p>理解 Coolify 的底层，有助于评估其技术稳定性和扩展性边界：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>容器化核心 (Docker-based)&lt;/strong>：Coolify 的一切皆容器。它不依赖 Kubernetes 的复杂编排，而是利用底层的 Docker Engine 运行应用，这保证了极低的资源消耗（主控节点 2C2G 即可运行）。&lt;/li>
&lt;li>&lt;strong>构建引擎 (Nixpacks)&lt;/strong>：采用目前非常先进的 Nixpacks（由 Railway 团队开源）替代传统的 Dockerfile 构建。它能更智能、更快速地解析代码库，生成极度优化的容器镜像。&lt;/li>
&lt;li>&lt;strong>控制面与数据面分离&lt;/strong>：
&lt;ul>
&lt;li>&lt;em>Control Plane（控制面）&lt;/em>：Coolify 面板本身，负责下发指令。&lt;/li>
&lt;li>&lt;em>Worker Nodes（工作节点）&lt;/em>：实际跑应用的服务器。即使 Coolify 面板宕机，由于底层是通过 Docker 运行，部署好的业务应用&lt;strong>不受影响&lt;/strong>，继续提供服务。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h3 id="四-竞品对比与市场分析-competitive-landscape">四、 竞品对比与市场分析 (Competitive Landscape)
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">比较维度&lt;/th>
&lt;th style="text-align: left">Coolify (自托管)&lt;/th>
&lt;th style="text-align: left">Vercel / Netlify&lt;/th>
&lt;th style="text-align: left">Heroku / Render&lt;/th>
&lt;th style="text-align: left">Kubernetes (K8s)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>成本&lt;/strong>&lt;/td>
&lt;td style="text-align: left">极低（仅需支付廉价 VPS 费用）&lt;/td>
&lt;td style="text-align: left">早期免费，后期扩展成本极高&lt;/td>
&lt;td style="text-align: left">中等偏高&lt;/td>
&lt;td style="text-align: left">极高（需专业运维团队和冗余机器）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>学习门槛&lt;/strong>&lt;/td>
&lt;td style="text-align: left">低（图形化界面）&lt;/td>
&lt;td style="text-align: left">极低&lt;/td>
&lt;td style="text-align: left">较低&lt;/td>
&lt;td style="text-align: left">极高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>扩展性&lt;/strong>&lt;/td>
&lt;td style="text-align: left">中（单机伸缩，暂无自动水平扩容）&lt;/td>
&lt;td style="text-align: left">高（Serverless，全球边缘节点）&lt;/td>
&lt;td style="text-align: left">高&lt;/td>
&lt;td style="text-align: left">极高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>数据隐私&lt;/strong>&lt;/td>
&lt;td style="text-align: left">极高（数据全在自己服务器）&lt;/td>
&lt;td style="text-align: left">低（托管在第三方）&lt;/td>
&lt;td style="text-align: left">低（托管在第三方）&lt;/td>
&lt;td style="text-align: left">极高（可私有化部署）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;strong>适用场景&lt;/strong>&lt;/td>
&lt;td style="text-align: left">独立开发、初创公司、内部系统&lt;/td>
&lt;td style="text-align: left">纯前端、重 SEO 网站、轻量 API&lt;/td>
&lt;td style="text-align: left">快速验证商业模式的 MVP&lt;/td>
&lt;td style="text-align: left">大型企业、高并发、微服务架构&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h3 id="五-产品经理的落地实施建议-actionable-strategy">五、 产品经理的落地实施建议 (Actionable Strategy)
&lt;/h3>&lt;p>如果你打算在团队中引入 Coolify，我建议采取以下策略以平衡资源与风险：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>切入场景：先内部后外部&lt;/strong>
&lt;ul>
&lt;li>不要一开始就把核心交易系统放上去。先用 Coolify 部署&lt;strong>内部管理后台、测试环境（Staging）、数据分析工具（Metabase）或官网博客&lt;/strong>。验证团队对其稳定性的掌握度。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>架构部署：隔离主控与生产&lt;/strong>
&lt;ul>
&lt;li>买一台轻量级 VPS 作为“主控节点”专门跑 Coolify 面板。&lt;/li>
&lt;li>将性能更好的服务器作为“工作节点”通过 SSH 挂载上去跑实际的业务和数据库。这样即便折腾面板，也不会影响线上业务。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>风险控制：关注 OS 层面运维&lt;/strong>
&lt;ul>
&lt;li>&lt;strong>劣势预警&lt;/strong>：Coolify 帮你解决了应用层的运维，但&lt;strong>不解决 Linux 操作系统底层的运维&lt;/strong>。服务器的内核升级、防火墙（UFW/iptables）配置、防 DDoS 攻击依然需要你处理。&lt;/li>
&lt;li>&lt;strong>强推备份&lt;/strong>：第一时间配置 S3 数据库自动备份策略。只要数据在，无论面板或服务器出什么问题，都能在 30 分钟内用一台新机器拉起所有服务。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>总结&lt;/strong>：Coolify 是一个典型的“用技术杠杆对抗资本”的优秀产品。它非常适合那些需要快速迭代、又希望把控基础设施成本的小型敏捷团队。&lt;/p></description></item><item><title>1panel使用教程｜云服务器使用教程</title><link>https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/</link><pubDate>Sun, 09 Mar 2025 16:14:31 +0800</pubDate><guid>https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/</guid><description>&lt;img src="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/index.png" alt="Featured image of post 1panel使用教程｜云服务器使用教程" />&lt;h3 id="1panel安装">1panel安装
&lt;/h3>&lt;p>官网：&lt;br>
&lt;a class="link" href="https://1panel.cn/docs/installation/online_installation/" target="_blank" rel="noopener"
>https://1panel.cn/docs/installation/online_installation/&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ubuntu&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">apt install curl &lt;span class="c1"># 如果下面一行提示curl没有&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> sudo bash quick_start.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1pctl --help &lt;span class="c1"># 查看是否安装成功&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="实战-----问题和解决方案">实战 &amp;mdash; 问题和解决方案
&lt;/h3>&lt;h4 id="腾讯云的windows服务器做远程hugo的dev服务器的时候出的问题--之前用过华为云的服务器做dev服务器明显腾讯做的不如华为">腾讯云的windows服务器做远程hugo的dev服务器的时候出的问题 （之前用过华为云的服务器做dev服务器，明显腾讯做的不如华为）
&lt;/h4>&lt;ol>
&lt;li>使用腾讯云自带的snv连接，卡的要死，所以用了windows自带的，mac上面又windows app作为远程连接&lt;/li>
&lt;li>使用openssh作为ssh作为服务器之后，存在总是断联问题，增加conf文件解决 &lt;a class="link" href="https://www.zata.cc/p/ssh%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/#%E8%A7%A3%E5%86%B3-ssh-%E8%BF%9E%E6%8E%A5%E8%BF%9C%E7%A8%8B%E4%B8%BB%E6%9C%BA%E8%B6%85%E6%97%B6%E6%9C%AA%E4%BD%BF%E7%94%A8%E8%87%AA%E5%8A%A8%E6%96%AD%E5%BC%80" target="_blank" rel="noopener"
>config文件解决ssh断联&lt;/a>&lt;/li>
&lt;li>git可以使用便携包，然后添加一下环境变量（里面的cmd文件夹），再重启服务器
&lt;img src="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-2.png"
width="1226"
height="954"
srcset="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-2_hu10924201580597598088.png 480w, https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-2_hu7787008948582728156.png 1024w"
loading="lazy"
alt="protable"
class="gallery-image"
data-flex-grow="128"
data-flex-basis="308px"
>&lt;/li>
&lt;li>使用windows远程服务器进行git pull总是卡死，最终给出的解决方案就是：使用github的http地址拉取项目，然后使用ssh地址同步&lt;/li>
&lt;/ol>
&lt;h4 id="云服务器修改时区设置">云服务器，修改时区设置
&lt;/h4>&lt;p>首先查看服务器时间，明显是错误的
&lt;img src="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image.png"
width="953"
height="741"
srcset="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image_hu2535172349089398868.png 480w, https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image_hu3072277793690704435.png 1024w"
loading="lazy"
alt="查看服务器时间"
class="gallery-image"
data-flex-grow="128"
data-flex-basis="308px"
>&lt;/p>
&lt;p>&lt;img src="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-1.png"
width="416"
height="72"
srcset="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-1_hu6252721194716937711.png 480w, https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-1_hu10619994981231364364.png 1024w"
loading="lazy"
alt="修改时区"
class="gallery-image"
data-flex-grow="577"
data-flex-basis="1386px"
>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 检查时区&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">date
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 通过手动链接时区文件来更改时区：&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 如果有/etc/timezone 文件，可以更新它以确保一致性，当然不更新也可以&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat /etc/timezone
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Asia/Shanghai&amp;#34;&lt;/span> &amp;gt; /etc/timezone
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="我自己使用1panel和云服务器的一些感悟">我自己使用1panel和云服务器的一些感悟
&lt;/h4>&lt;p>&lt;strong>在云服务器部署碰到的麻烦事：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>1panel 的运行环境模式，会自动执行脚本，虽然它创建了一个docker容器，但是如果你进去想要把它的脚本关掉，它会自启动，而如果你把它的这个环境停掉，docker容器就消失了，所以不要用它的环境容器做什么事情&lt;/li>
&lt;li>1panel的docker连接之后要先执行一下su，不然的话命令是不好操作的，比如就没有补全功能&lt;/li>
&lt;li>要去/ect/hosts去设置一下github的ip地址解析，不然会很慢&lt;/li>
&lt;li>云服务器如果是国内厂商的，最好设置一下镜像源，不然的话会下载非常慢，比如pip install的时候&lt;/li>
&lt;/ol>
&lt;h4 id="1panel的反向代理">1panel的反向代理
&lt;/h4>&lt;p>&lt;img src="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-3.png"
width="772"
height="954"
srcset="https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-3_hu14712500426784273809.png 480w, https://www.zata.cc/p/1panel%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/image-3_hu3321060561341669935.png 1024w"
loading="lazy"
alt="使用OpenResty"
class="gallery-image"
data-flex-grow="80"
data-flex-basis="194px"
>&lt;/p></description></item></channel></rss>