<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0"><channel><title>我不是咕咕鸽</title><link>https://blog.laoda.de</link><atom:link href="https://blog.laoda.de/rss.xml" rel="self" type="application/rss+xml"/><description>VPS折腾不完全记录</description><generator>Halo v2.23.2</generator><language>zh-cn</language><image><url>https://blog.laoda.de/upload/guguge.webp</url><title>我不是咕咕鸽</title><link>https://blog.laoda.de</link></image><lastBuildDate>Sat, 11 Apr 2026 19:21:20 GMT</lastBuildDate><item><title><![CDATA[德国买iPhone退税全流程实测：19%消费税能退多少？踩坑+避坑全记录]]></title><link>https://blog.laoda.de/archives/germany-iphone-tax-refund-guide</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%BE%B7%E5%9B%BD%E4%B9%B0iPhone%E9%80%80%E7%A8%8E%E5%85%A8%E6%B5%81%E7%A8%8B%E5%AE%9E%E6%B5%8B%EF%BC%9A19%25%E6%B6%88%E8%B4%B9%E7%A8%8E%E8%83%BD%E9%80%80%E5%A4%9A%E5%B0%91%EF%BC%9F%E8%B8%A9%E5%9D%91%2B%E9%81%BF%E5%9D%91%E5%85%A8%E8%AE%B0%E5%BD%95&amp;url=/archives/germany-iphone-tax-refund-guide" width="1" height="1" alt="" style="opacity:0;">
<p>好久没和大家更新博客了，这段时间真的事情巨多（家里的事情+公司出差+回来之后研究小龙虾和Claude Code），一直想着有时间就要更新一下，但是每次回到家忙完事情已经挺晚了，也感觉累了，就迟迟没有动手写博客。</p>
<p>今天趁着闲暇时间，赶紧和大家更新一波。</p>
<h2 id="购机篇">购机篇</h2>
<p>我在3月份的时候出差去了趟德国，工作结束之后，我突然心血来潮说要不要整一部国际版的iPhone。</p>
<p>熟悉咕咕的小伙伴知道，其实我目前有一台美版的iPhone SE3在服役中（支持实体SIM+eSIM），手感非常好，续航问题我也通过背夹电池的方法解决了（官方方案的升级版，后续和大家分享，可以重度使用一天），但问题就是屏幕确实有点小了，打字也容易按错。</p>
<p>"这次出差算是比较成功的，下次带队不知道是啥时候了，买台iPhone 17 Pro Max奖励一下自己，也顺便给大家实测一下在德国购买iPhone的流程和后续的退税流程。"</p>
<p>嗯，我是这么说服我自己的。虽然我知道港版功能一样，而且更便宜……</p>
<p>德国这边对换手机这件事情好像他们不怎么在意，地铁公交上很多都用的旧手机。因为我第二天就要出发返回国内，我先看了下小红书攻略，说最好提前预约，然后门店提货，会更稳一点，于是我就用我的SE3 在苹果的德国官网上下单了一台蓝色 512G的iPhone 17 Pro Max，用的Apple Pay选的Chase的信用卡付款的，选择线下提货的地点是慕尼黑玛丽亚广场的苹果官方旗舰店。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145346-1.webp&amp;size=m" alt="c8a62bede31c33f7ae35f6174e36d34e.png"></p>
<p>早起过去，人果然很多。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145344-1.webp&amp;size=m" alt="IMG20260316114848.jpg"></p>
<p>和工作人员说明来取货，出示了订单和二维码，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145340-1.webp&amp;size=m" alt="b55f6bf87662b37b6983b935ce873670.png"></p>
<p>很快小姐姐就给我拿来了手机。</p>
<p>图片 小姐姐</p>
<p>然后我表示我需要退税，小姐姐似乎不太懂，询问了身边的同事，叽里咕噜的，德语我们也听不懂，然后小姐姐去拿来了一张单子，长这样：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145337-1.webp&amp;size=m" alt="微信图片_20260402135927_278_361.jpg"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F03%2F101000-1.webp&amp;size=m" alt="DJI_20260316093501_0052_D-0004.png"></p>
<p>你敢相信，在德国给外国人的退税的单子居然是德语的，而且小姐姐很抱歉地说没有英语的版本，可能需要我们自己借助翻译填写一下……</p>
<p>而且由于我们是线上下单的，店里并没有给我们发票。（我查询了一下发现退税需要有退税单和发票还有实物的）</p>
<h2 id="退税踩坑">退税踩坑</h2>
<p>我虽然表示震惊，但也接受了，凭借我多年官网购买iPhone的经验，苹果官方肯定会给我邮件发一个发票的，而且看起来这个表是苹果官方的退税，没有中间商赚差价，可以退全额，你知道德国的电子产品消费税是多少吗？19% ！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145335-1.webp&amp;size=m" alt="c52a32d17627facb4ba29e9596383aca.png"></p>
<p>怪不得感觉大家都换新手机不感冒……</p>
<p>然而新的问题出现了……</p>
<p>我下午翻看邮件，一直没有等到苹果给我发的发票，没有发票就意味着海关不可能给我退税，我又查了下，发现在官网购买的手机，电子发票可能是在24-48小时内送达到邮箱！我的机票是第二天早上的，时间上来不及了。</p>
<p>于是我和同事又感受了大概四十分钟的地铁，从慕尼黑机场的希尔顿返回到玛丽亚广场。我找了个理由和店员说支付的时候卡弄错了，想要把这台网上订的、上午刚提的iPhone退了，然后换一张卡在店里直接买一台。</p>
<p>这次接待的是一个小哥，小哥欣然同意表示没问题，简单检查了手机之后，直接给我退了款，然后我换了一张招行的卡支付，他还是把这台手机给了我，并熟练地给我global blue的单子，告诉我可以退大概10%的税，而且在玛丽亚广场不远的地方有global blue的柜台。（同事略懂日语，还和小哥谈起了他手臂上的纹身 = =）</p>
<p>我们过去之后工作人员给盖了章，然后工作人员让我出示了信用卡（因为我打算退到信用卡里），最后告诉了我慕尼黑机场的海关的位置，以及告诉我敲完海关的章需要把信封交给机场的global blue的柜台，整体体验非常丝滑。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145331-1.webp&amp;size=m" alt="IMG20260316202639.jpg"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145340-1_1.webp&amp;size=m" alt="IMG_20260402_144825.jpg"></p>
<h2 id="退税篇">退税篇</h2>
<p>手机总算告一段落，但是还有一个问题出现了……</p>
<p>本来我打算直接拆封使用的，但是我还是做了一下功课——购买的产品不能使用，一旦使用了之后海关不给退税！</p>
<p>所以还是只能老老实实装在包里，等第二天退完税之后使用。</p>
<p>我这次是慕尼黑 T1 航站楼出发，海关在 B 区，Global Blue 就在对面，流程还算比较清楚。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145328-1.webp&amp;size=m" alt="IMG20260316144455.jpg"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145339-1.webp&amp;size=m" alt="4913918cdc827cf000974b0dbb414e39.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145332-1.webp&amp;size=m" alt="bcd887f1b03eb755000264551cdf02e9.png"></p>
<p>如果你买的东西是走 Global Blue 退税的，而且放在托运行李箱里，值机的时候一定要先跟工作人员说：</p>
<blockquote>
 <p>箱子里有 tax free items</p>
</blockquote>
<p>工作人员会先给你的行李箱贴标签，然后你拿着箱子去海关那边盖章，盖完之后海关会直接帮你把行李托运走，因为前面已经贴好标签了，所以不用担心箱子乱跑。</p>
<p>之后你再去对面的 Global Blue 柜台办后续就可以。</p>
<p>如果退税物品是在随身行李里，正常来说是要过完安检以后，再去里面的海关检查盖章。</p>
<p>不过我这次也直接拿给外面的海关看了，结果他也给我盖章了，所以我这次就一起退掉了，但这个我感觉不一定每次都行，可能还是看现场工作人员。</p>
<p><strong>几个小经验：</strong></p>
<ul>
 <li>小额的东西一般不太查</li>
 <li>大额的基本都会查</li>
 <li>买的东西千万别拆封</li>
</ul>
<p>这次买的手机，海关那边检查了非常久，反复用手指抠，问我是不是拆过。所以像 iPhone 这种高价值商品，千万别提前拆，不然很容易影响退税。</p>
<p>顺便说一下，这次除了手机，我在 dm 也顺手买了一些东西。dm 的退税流程和 Global Blue 不太一样，麻烦不少——要么你下次回店里，拿海关盖章的小票再去退；要么走国内的易退税邮寄处理。两种我个人觉得都不算方便，有机会还是直接去店里退更省事。不过这次 dm 的东西，海关是完全没检查。</p>
<h2 id="最终到手价格">最终到手价格</h2>
<p>最后，看看这部手机退税下来一共花了多少钱：</p>
<p>手机原价 13525.96 - 汇率优惠 13.53 - Global Blue 退税 1340.78 - 招行1%返现 131.46 = <strong>12040.19 元</strong></p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145313-1.webp&amp;size=m" alt="截屏 2026-04-02 14.19.48.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F02%2F145306-1.webp&amp;size=m" alt="微信图片_20260402142038_1463_68.jpg" style="zoom:50%;">
<p>招行那个1%的返现好像实际到账不足1%？</p>
<p>比起国内还是贵了不少的。</p>
<h2 id="关于德国版-iPhone">关于德国版 iPhone</h2>
<p>最后，给大家看一下德国版本的iPhone有啥不一样的地方：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F03%2F100929-1.webp&amp;size=m" alt="微信图片_20260403080935_283_361.jpg" style="zoom:50%;">
<p>其实除了这个CE标识，其他的和港版应该是一样的，日常eSIM需求的更推荐港版，我这个就当纪念了 = =。</p>]]></description><guid isPermaLink="false">/archives/germany-iphone-tax-refund-guide</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F04%2F03%2F101449-1.webp&amp;size=m" type="image/jpeg" length="143996"/><category>有用的小知识</category><pubDate>Fri, 3 Apr 2026 02:15:29 GMT</pubDate></item><item><title><![CDATA[10 分钟搭建一个支持超过 1000 种不同格式的在线文件转换器——ConvertX｜好玩儿的 Docker 项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-convertx</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=10%20%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81%E8%B6%85%E8%BF%87%201000%20%E7%A7%8D%E4%B8%8D%E5%90%8C%E6%A0%BC%E5%BC%8F%E7%9A%84%E5%9C%A8%E7%BA%BF%E6%96%87%E4%BB%B6%E8%BD%AC%E6%8D%A2%E5%99%A8%E2%80%94%E2%80%94ConvertX%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84%20Docker%20%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-convertx" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>好久没更新了，这周来和大家分享一个自托管的在线文件转换器。支持超过一千种不同格式。使用 TypeScript、Bun 和 Elysia 编写。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150219-1.webp&amp;size=m" alt="e3a1dbdc76a602c085010e7ba78c6e40.png"></p>
<h2 id="2--ConvertX-简介">2. ConvertX 简介</h2>
<p><strong>功能特性</strong></p>
<ul>
 <li>将文件转换为不同格式</li>
 <li>一次处理多个文件</li>
 <li>密码保护</li>
 <li>多个账户</li>
</ul>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150217-1.webp&amp;size=m" alt="5da3095bb57e3702117dda7268c82b2d.png"></p>
<p>支持转换的类型</p>
<table>
 <thead>
  <tr>
   <th>Converter</th>
   <th>Use case</th>
   <th>Converts from</th>
   <th>Converts to</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><a href="https://inkscape.org/">Inkscape</a></td>
   <td>Vector images</td>
   <td>7</td>
   <td>17</td>
  </tr>
  <tr>
   <td><a href="https://github.com/libjxl/libjxl">libjxl</a></td>
   <td>JPEG XL</td>
   <td>11</td>
   <td>11</td>
  </tr>
  <tr>
   <td><a href="https://github.com/RazrFalcon/resvg">resvg</a></td>
   <td>SVG</td>
   <td>1</td>
   <td>1</td>
  </tr>
  <tr>
   <td><a href="https://github.com/libvips/libvips">Vips</a></td>
   <td>Images</td>
   <td>45</td>
   <td>23</td>
  </tr>
  <tr>
   <td><a href="https://github.com/strukturag/libheif">libheif</a></td>
   <td>HEIF</td>
   <td>2</td>
   <td>4</td>
  </tr>
  <tr>
   <td><a href="https://tug.org/xetex/">XeLaTeX</a></td>
   <td>LaTeX</td>
   <td>1</td>
   <td>1</td>
  </tr>
  <tr>
   <td><a href="https://calibre-ebook.com/">Calibre</a></td>
   <td>E-books</td>
   <td>26</td>
   <td>19</td>
  </tr>
  <tr>
   <td><a href="https://www.libreoffice.org/">LibreOffice</a></td>
   <td>Documents</td>
   <td>41</td>
   <td>22</td>
  </tr>
  <tr>
   <td><a href="https://github.com/TomWright/dasel">Dasel</a></td>
   <td>Data Files</td>
   <td>5</td>
   <td>4</td>
  </tr>
  <tr>
   <td><a href="https://pandoc.org/">Pandoc</a></td>
   <td>Documents</td>
   <td>43</td>
   <td>65</td>
  </tr>
  <tr>
   <td><a href="https://github.com/mvz/email-outlook-message-perl">msgconvert</a></td>
   <td>Outlook</td>
   <td>1</td>
   <td>1</td>
  </tr>
  <tr>
   <td>VCF to CSV</td>
   <td>Contacts</td>
   <td>1</td>
   <td>1</td>
  </tr>
  <tr>
   <td><a href="https://dvisvgm.de/">dvisvgm</a></td>
   <td>Vector images</td>
   <td>4</td>
   <td>2</td>
  </tr>
  <tr>
   <td><a href="https://imagemagick.org/">ImageMagick</a></td>
   <td>Images</td>
   <td>245</td>
   <td>183</td>
  </tr>
  <tr>
   <td><a href="http://www.graphicsmagick.org/">GraphicsMagick</a></td>
   <td>Images</td>
   <td>167</td>
   <td>130</td>
  </tr>
  <tr>
   <td><a href="https://github.com/assimp/assimp">Assimp</a></td>
   <td>3D Assets</td>
   <td>77</td>
   <td>23</td>
  </tr>
  <tr>
   <td><a href="https://ffmpeg.org/">FFmpeg</a></td>
   <td>Video</td>
   <td>~472</td>
   <td>~199</td>
  </tr>
  <tr>
   <td><a href="https://potrace.sourceforge.net/">Potrace</a></td>
   <td>Raster to vector</td>
   <td>4</td>
   <td>11</td>
  </tr>
  <tr>
   <td><a href="https://github.com/visioncortex/vtracer">VTracer</a></td>
   <td>Raster to vector</td>
   <td>8</td>
   <td>1</td>
  </tr>
  <tr>
   <td><a href="https://github.com/microsoft/markitdown">Markitdown</a></td>
   <td>Documents</td>
   <td>6</td>
   <td>1</td>
  </tr>
 </tbody>
</table>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方 GitHub 地址：<a href="https://github.com/C4illin/ConvertX">https://github.com/C4illin/ConvertX</a> （目前 15.3k 个 star，欢迎大家去给项目点星星！）</p>
<p>当然如果你想自己用 docker 搭建一个，那我们就继续往下！</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的 <a href="http://gao.ee/lca">莱卡云服务器</a>，建议服务器内存 1G 以上，当然你也可以选择其他 <a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩周补充-----">5. 搭建视频（过俩周补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/convertx

cd /root/data/docker_data/convertx
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  convertx:
    image: ghcr.io/c4illin/convertx
    container_name: convertx
    restart: unless-stopped
    ports:
      - "3001:3000"
    environment:
      - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken123412 # will use randomUUID() if unset
      # - HTTP_ALLOWED=true # uncomment this if accessing it over a non-https connection 如果通过 http 访问的话取消这行注释
      - LANGUAGE=zh
    volumes:
      - ./data:/app/data
</code></pre>
<p>其中的左边的<code>3001</code>可以改成服务器上没有用过的端口。</p>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h4 id="环境变量">环境变量</h4>
<p>所有都是可选的，但建议设置 <code>JWT_SECRET</code>。</p>
<table>
 <thead>
  <tr>
   <th>Name</th>
   <th>Default</th>
   <th>Description</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>JWT_SECRET</td>
   <td>when unset it will use the value from randomUUID()</td>
   <td>用于签署 JSON Web Token 的一串密钥字符串</td>
  </tr>
  <tr>
   <td>ACCOUNT_REGISTRATION</td>
   <td>false</td>
   <td>允许用户注册账户</td>
  </tr>
  <tr>
   <td>HTTP_ALLOWED</td>
   <td>false</td>
   <td>允许 HTTP 连接，仅在本地部署的时候将它设置为 true</td>
  </tr>
  <tr>
   <td>ALLOW_UNAUTHENTICATED</td>
   <td>false</td>
   <td>允许未认证用户使用该服务，仅在本地部署的时候将它设置为 true。</td>
  </tr>
  <tr>
   <td>AUTO_DELETE_EVERY_N_HOURS</td>
   <td>24</td>
   <td>每 n 小时检查一次，删除超过 n 小时的文件，设置为 0 表示禁用。</td>
  </tr>
  <tr>
   <td>WEBROOT</td>
   <td></td>
   <td>将根路径设置为 "/convert" 的地址将在 "example.com/convert/" 上提供网站。</td>
  </tr>
  <tr>
   <td>FFMPEG_ARGS</td>
   <td></td>
   <td>传递给 ffmpeg 输入文件的参数，例如 <code>-hwaccel vaapi</code>。有关硬件加速的更多信息，请参见 <a href="https://github.com/C4illin/ConvertX/issues/190">#190</a>。</td>
  </tr>
  <tr>
   <td>FFMPEG_OUTPUT_ARGS</td>
   <td></td>
   <td>传递给 ffmpeg 输出的参数，例如 <code>-preset veryfast</code></td>
  </tr>
  <tr>
   <td>HIDE_HISTORY</td>
   <td>false</td>
   <td>隐藏历史页面</td>
  </tr>
  <tr>
   <td>LANGUAGE</td>
   <td>en</td>
   <td>用于格式化日期字符串的语言，指定为 <a href="https://en.wikipedia.org/wiki/IETF_language_tag">BCP 47 language tag</a></td>
  </tr>
  <tr>
   <td>UNAUTHENTICATED_USER_SHARING</td>
   <td>false</td>
   <td>所有未经身份验证用户共享转换历史记录</td>
  </tr>
  <tr>
   <td>MAX_CONVERT_PROCESS</td>
   <td>0</td>
   <td>允许的最大并发转换进程数量。设置为 0 表示无限制。</td>
  </tr>
 </tbody>
</table>
<p>按需添加修改，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3001</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3001  #查看 3001 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-convertx">6.4 启动 convertx</h3>
<pre><code>cd /root/data/docker_data/convertx

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150655-1.webp&amp;size=m" alt="662decf436731fa2acf7a276e4af9caf.png"></p>
<p>镜像还是比较大的……</p>
<p>耐心等待拉取好镜像，出现 <code>Created</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3001</code> 访问了。</p>
<p>但是我们部署在公网一定要考虑使用反向代理工具配置 SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo 上 6 位数字的 xyz 续费永远都是 0.99 美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150210-1.webp&amp;size=m" alt="0a6c012bb847558679e499f447dd4958.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150207-1.webp&amp;size=m" alt="61a4b0f2f2c6bb56b3bf540e00deb8a5.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150204-1.webp&amp;size=m" alt="ceb23ce98beed6ac28add2b03d4e53e8.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150203-1.webp&amp;size=m" alt="894dac73d5b90a9032806b61cdf22540.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150200-1.webp&amp;size=m" alt="67b28075187f39a44dce4b23b9228abb.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3001</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 convertx 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 convertx 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3001/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，所见即所得。</p>
<p>先注册账号：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150155-1.webp&amp;size=m" alt="45e7bc9343633faae0922c3f9a788670.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150153-1.webp&amp;size=m" alt="f1a7c788c803a41e6aa3ccb88607c5fd.png"></p>
<p>JPG 转换成 webp</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150151-1.webp&amp;size=m" alt="8475bb89d272567691366dd6c838f86b.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150148-1.webp&amp;size=m" alt="f65aa6b232020dc70071d0cea24f442c.png"></p>
<p>MP4 转 AVI</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150146-1.webp&amp;size=m" alt="2e655386026439a4f31bad8221504d7f.png"></p>
<p>正常转换。</p>
<p>转换历史：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150143-1.webp&amp;size=m" alt="11626ac66e09b45b5d7efe77b02e8d10.png"></p>
<p>服务器里还是能看到文件的，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2026%2F01%2F20%2F150132-1.webp&amp;size=m" alt="97c9f37455cfbabc34e0049b079356ef.png"></p>
<h3 id="8-1-更新-convertx">8.1 更新 convertx</h3>
<p>这个项目后续会持续有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/convertx

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-convertx">8.2 卸载 convertx</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/convertx

docker compose down

cd ..

rm -rf /root/data/docker_data/convertx  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--使用问题">9. 使用问题</h2>
<p>大家使用上有什么心得或者问题，欢迎评论区交流～</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/C4illin/ConvertX/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/C4illin/ConvertX">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者 <a href="https://github.com/C4illin">@C4illin</a> 的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star。</p>
<h2 id="参考资料">参考资料</h2>
<p>官方 GitHub：<a href="https://github.com/C4illin/ConvertX">https://github.com/C4illin/ConvertX</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-convertx</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Tue, 20 Jan 2026 07:12:49 GMT</pubDate></item><item><title><![CDATA[十分钟搭建一个 AI 驱动的图表生成器——Next-AI-Draw.io｜好玩儿的 Docker 项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-next-ai-draw-io</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%20AI%20%E9%A9%B1%E5%8A%A8%E7%9A%84%E5%9B%BE%E8%A1%A8%E7%94%9F%E6%88%90%E5%99%A8%E2%80%94%E2%80%94Next-AI-Draw.io%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84%20Docker%20%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-next-ai-draw-io" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>好久没更新了，这周来和大家分享一个 AI 驱动的图表生成器——Next-AI-Draw.io</p>
<h2 id="2--Next-AI-Draw-io-简介">2. Next-AI-Draw.io 简介</h2>
<p>Next-AI-Draw.io 是一个集成了 AI 功能的 Next.js 网页应用，与 draw.io 图表无缝结合。通过自然语言命令和 AI 辅助可视化来创建、修改和增强图表。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170220-1.webp&amp;size=m" alt="9dc17920a8529ad875088874df11e1c7.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170218-1.webp&amp;size=m" alt="0284f7edc67110d515a3edabf7ba418a.png"></p>
<p><strong>功能特性</strong></p>
<ul>
 <li><strong>LLM 驱动的图表创建</strong>：利用大语言模型通过自然语言命令直接创建和操作 draw.io 图表</li>
 <li><strong>基于图像的图表复制</strong>：上传现有图表或图像，让 AI 自动复制和增强</li>
 <li><strong>PDF 和文本文件上传</strong>：上传 PDF 文档和文本文件，提取内容并从现有文档生成图表</li>
 <li><strong>AI 推理过程显示</strong>：查看支持模型的 AI 思考过程（OpenAI o1/o3、Gemini、Claude 等）</li>
 <li><strong>图表历史记录</strong>：全面的版本控制，跟踪所有更改，允许您查看和恢复 AI 编辑前的图表版本</li>
 <li><strong>交互式聊天界面</strong>：与 AI 实时对话来完善您的图表</li>
 <li><strong>云架构图支持</strong>：专门支持生成云架构图（AWS、GCP、Azure）</li>
 <li><strong>动画连接器</strong>：在图表元素之间创建动态动画连接器，实现更好的可视化效果</li>
</ul>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方 GitHub 地址：<a href="https://github.com/DayuanJiang/next-ai-draw-io">https://github.com/DayuanJiang/next-ai-draw-io</a> （目前 13k 个 star，欢迎大家去给项目点星星！）</p>
<p>Demo 地址：<a href="https://next-ai-drawio.jiang.jp/">https://next-ai-drawio.jiang.jp/</a></p>
<p>当然如果你体验完还想自己用 docker 搭建一个，那我们就继续往下！</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的 <a href="http://gao.ee/lca">莱卡云服务器</a>，建议服务器内存 1G 以上，当然你也可以选择其他 <a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩周补充-----">5. 搭建视频（过俩周补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/drawioai

cd /root/data/docker_data/drawioai
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">name: nextaidrawio
services:
    next-ai-draw-io:
        ports:
            - 3001:3000
        env_file:
            - .env
        image: ghcr.io/dayuanjiang/next-ai-draw-io:latest
</code></pre>
<p>其中的左边的<code>3001</code>可以改成服务器上没有用过的端口。</p>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<p>接着我们来编辑下<code>.env</code></p>
<pre><code class="language-bash">cd /root/data/docker_data/drawioai
vim .env
</code></pre>
<p>粘贴如下内容：</p>
<pre><code class="language-env"># AI Provider Configuration
# AI_PROVIDER: Which provider to use
# Options: bedrock, openai, anthropic, google, azure, ollama, openrouter, deepseek, siliconflow, gateway
# Default: bedrock
AI_PROVIDER=bedrock

# AI_MODEL: The model ID for your chosen provider (REQUIRED)
AI_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0

# AWS Bedrock Configuration
# AWS_REGION=us-east-1
# AWS_ACCESS_KEY_ID=your-access-key-id
# AWS_SECRET_ACCESS_KEY=your-secret-access-key
# Note: Claude and Nova models support reasoning/extended thinking
# BEDROCK_REASONING_BUDGET_TOKENS=12000  # Optional: Claude reasoning budget in tokens (1024-64000)
# BEDROCK_REASONING_EFFORT=medium        # Optional: Nova reasoning effort (low/medium/high)

# OpenAI Configuration
# OPENAI_API_KEY=sk-...
# OPENAI_BASE_URL=https://api.openai.com/v1  # Optional: Custom OpenAI-compatible endpoint
# OPENAI_ORGANIZATION=org-...  # Optional
# OPENAI_PROJECT=proj_...      # Optional
# Note: o1/o3/gpt-5 models automatically enable reasoning summary (default: detailed)
# OPENAI_REASONING_EFFORT=low   # Optional: Reasoning effort (minimal/low/medium/high) - for o1/o3/gpt-5
# OPENAI_REASONING_SUMMARY=detailed  # Optional: Override reasoning summary (none/brief/detailed)

# Anthropic (Direct) Configuration
# ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_BASE_URL=https://your-custom-anthropic/v1
# ANTHROPIC_THINKING_TYPE=enabled            # Optional: Anthropic extended thinking (enabled)
# ANTHROPIC_THINKING_BUDGET_TOKENS=12000     # Optional: Budget for extended thinking in tokens

# Google Generative AI Configuration
# GOOGLE_GENERATIVE_AI_API_KEY=...
# GOOGLE_BASE_URL=https://generativelanguage.googleapis.com/v1beta  # Optional: Custom endpoint
# GOOGLE_CANDIDATE_COUNT=1                   # Optional: Number of candidates to generate
# GOOGLE_TOP_K=40                            # Optional: Top K sampling parameter
# GOOGLE_TOP_P=0.95                          # Optional: Nucleus sampling parameter
# Note: Gemini 2.5/3 models automatically enable reasoning display (includeThoughts: true)
# GOOGLE_THINKING_BUDGET=8192                # Optional: Gemini 2.5 thinking budget in tokens (for more/less thinking)
# GOOGLE_THINKING_LEVEL=high                 # Optional: Gemini 3 thinking level (low/high)

# Azure OpenAI Configuration
# Configure endpoint using ONE of these methods:
#   1. AZURE_RESOURCE_NAME - SDK constructs: https://{name}.openai.azure.com/openai/v1{path}
#   2. AZURE_BASE_URL - SDK appends /v1{path} to your URL
# If both are set, AZURE_BASE_URL takes precedence.
# AZURE_RESOURCE_NAME=your-resource-name
# AZURE_API_KEY=...
# AZURE_BASE_URL=https://your-resource.openai.azure.com/openai  # Alternative: Custom endpoint
# AZURE_REASONING_EFFORT=low                 # Optional: Azure reasoning effort (low, medium, high)
# AZURE_REASONING_SUMMARY=detailed

# Ollama (Local) Configuration
# OLLAMA_BASE_URL=http://localhost:11434/api  # Optional, defaults to localhost
# OLLAMA_ENABLE_THINKING=true                 # Optional: Enable thinking for models that support it (e.g., qwen3)

# OpenRouter Configuration
# OPENROUTER_API_KEY=sk-or-v1-...
# OPENROUTER_BASE_URL=https://openrouter.ai/api/v1  # Optional: Custom endpoint

# DeepSeek Configuration
# DEEPSEEK_API_KEY=sk-...
# DEEPSEEK_BASE_URL=https://api.deepseek.com/v1  # Optional: Custom endpoint

# SiliconFlow Configuration (OpenAI-compatible)
# Base domain can be .com or .cn, defaults to https://api.siliconflow.com/v1
# SILICONFLOW_API_KEY=sk-...
# SILICONFLOW_BASE_URL=https://api.siliconflow.com/v1  # Optional: switch to https://api.siliconflow.cn/v1 if needed

# Vercel AI Gateway Configuration
# Get your API key from: https://vercel.com/ai-gateway
# Model format: "provider/model" e.g., "openai/gpt-4o", "anthropic/claude-sonnet-4-5"
# AI_GATEWAY_API_KEY=...

# Langfuse Observability (Optional)
# Enable LLM tracing and analytics - https://langfuse.com
# LANGFUSE_PUBLIC_KEY=pk-lf-...
# LANGFUSE_SECRET_KEY=sk-lf-...
# LANGFUSE_BASEURL=https://cloud.langfuse.com  # EU region, use https://us.cloud.langfuse.com for US

# Temperature (Optional)
# Controls randomness in AI responses. Lower = more deterministic.
# Leave unset for models that don't support temperature (e.g., GPT-5.1 reasoning models)
# TEMPERATURE=0

# Access Control (Optional)
# ACCESS_CODE_LIST=your-secret-code,another-code

# Draw.io Configuration (Optional)
# NEXT_PUBLIC_DRAWIO_BASE_URL=https://embed.diagrams.net  # Default: https://embed.diagrams.net
# Use this to point to a self-hosted draw.io instance

# PDF Input Feature (Optional)
# Enable PDF file upload to extract text and generate diagrams
# Enabled by default. Set to "false" to disable.
# ENABLE_PDF_INPUT=true
# NEXT_PUBLIC_MAX_EXTRACTED_CHARS=150000  # Max characters for PDF/text extraction (default: 150000)
</code></pre>
<p>这里头有很多选项可以开启，当然你也可以不管它，到网页端输入，这样的话就保存在本地浏览器里了，如果在这边输入，所有知道这个网址的人都能用你的 AI 模型。</p>
<p>假设我们用的 OPEN AI 的，其实<code>.env</code>里面只要这仨：</p>
<pre><code class="language-env">AI_PROVIDER=openai
AI_MODEL=gpt-4o
OPENAI_API_KEY=your_api_key
</code></pre>
<p><code>your_api_key</code>改成你的 API 密钥。</p>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3001</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3001  #查看 3001 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-drawioai">6.4 启动 drawioai</h3>
<pre><code>cd /root/data/docker_data/drawioai

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3001</code> 访问了。</p>
<p>但是我们部署在公网一定要考虑使用反向代理工具配置 SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo 上 6 位数字的 xyz 续费永远都是 0.99 美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170211-1.webp&amp;size=m" alt="1c160f28afd3549159df3efa2507ad0c.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170209-1.webp&amp;size=m" alt="c359c92172657c5667c6a1738b214511.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170200-1.webp&amp;size=m" alt="940b5b933d91851bb44423d5bfc3f628.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170156-1.webp&amp;size=m" alt="46b8997021848567235e69ee8b0be54f.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170151-1.webp&amp;size=m" alt="e2fed6006e075057bacdb57857e516b7.png" style="zoom: 50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3001</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 drawioai 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 drawioai 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3001/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，所见即所得。</p>
<p>登录页，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F171446.webp&amp;size=m" alt="ccd17e50213ceede7348a39b298f3085.png"></p>
<p>语言设置，改成中文，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F171509.webp&amp;size=m" alt="b0257ee37eafc1d9f205cf1858ab48fd.png"></p>
<p>简单展示</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F171532.webp&amp;size=m" alt="fead7ea8e6e781129d1c91dd03ee7b02.png"></p>
<p>右边可以输入提示词，比如让它画一只猫猫，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F171552.webp&amp;size=m" alt="02798e80fde95bc63142b86cfc83dc33.png"></p>
<p>画的熊猫不太像……</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170127-1.webp&amp;size=m" alt="b86441ae7cc00d5bab3ae0032ffa9cad.png"></p>
<p>当然你也可以隐藏掉这个提示词输入框，把它当成一个普通的画图软件来用，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170026-1.webp&amp;size=m" alt="b821ac8ceac261079ae31b3998e2b55c.png"></p>
<p>如果用默认的，其实是用的项目作者的 API，速率可能会有限制，当然用自己的 API 就没有这个问题了，如果手上富裕，也可以考虑捐赠作者，支持开源项目长久发展。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F12%2F18%2F170603.webp&amp;size=m" alt="727fd49d8064f8e7fae8d934daf5183f.png"></p>
<h3 id="8-1-更新-drawioai">8.1 更新 drawioai</h3>
<p>这个项目后续会持续有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/drawioai

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-drawioai">8.2 卸载 drawioai</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/drawioai

docker compose down

cd ..

rm -rf /root/data/docker_data/drawioai  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--使用问题">9. 使用问题</h2>
<p>那个保存按钮点了似乎没有任何反馈……</p>
<p>不过画的图导出是没问题的。</p>
<p>大家使用上有什么心得或者问题，欢迎评论区交流～</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/DayuanJiang/next-ai-draw-io/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/DayuanJiang/next-ai-draw-io">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者 <a href="https://github.com/DayuanJiang?tab=repositories">@DayuanJiang</a> 的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star。</p>
<h2 id="参考资料">参考资料</h2>
<p>官方 GitHub：<a href="https://github.com/DayuanJiang/next-ai-draw-io">https://github.com/DayuanJiang/next-ai-draw-io</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-next-ai-draw-io</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Thu, 18 Dec 2025 09:11:24 GMT</pubDate></item><item><title><![CDATA[十分钟搭建一个「万物皆可存」的智能书签应用——karakeep｜好玩儿的 Docker 项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-karakeep</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E3%80%8C%E4%B8%87%E7%89%A9%E7%9A%86%E5%8F%AF%E5%AD%98%E3%80%8D%E7%9A%84%E6%99%BA%E8%83%BD%E4%B9%A6%E7%AD%BE%E5%BA%94%E7%94%A8%E2%80%94%E2%80%94karakeep%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84%20Docker%20%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-karakeep" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>好久没更新了，这周来和大家分享一个好用的书签工具——Karakeep</p>
<h2 id="2--karakeep-简介">2. karakeep 简介</h2>
<p>Karakeep（前身为 Hoarder）是一款可自托管的「万物皆可存」书签应用，专为数据囤积爱好者打造，融入一丝 AI 魔法。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094935-1.webp&amp;size=m" alt="b877b9e2ebadea6bd7eb91991a4744e4.png"></p>
<p><strong>功能</strong></p>
<ul>
 <li>🔗 书签链接、记录简单笔记，并存储图片和 PDF 文件。</li>
 <li>⬇️ 自动抓取链接标题、描述和预览图。</li>
 <li>📋 将书签整理到不同列表中。</li>
 <li>🔎 全文本搜索所有存储内容。</li>
 <li>✨ 基于 AI（类似 ChatGPT）自动打标签和生成摘要。支持使用 Ollama 运行本地模型！</li>
 <li>🤖 规则引擎，实现自定义管理。</li>
 <li>🎆 图像 OCR，提取图片中的文字。</li>
 <li>🔖 Chrome 插件和 Firefox 扩展，快速添加书签。</li>
 <li>📱 iOS 应用和 Android 应用。</li>
 <li>📰 从 RSS 订阅源自动归档内容。</li>
 <li>🔌 REST API 和多种客户端。</li>
 <li>🌐 多语言支持。</li>
 <li>🖍️ 标记并保存归档内容中的高亮片段。</li>
 <li>🗄️ 完整页面归档（使用 monolith），防止链接失效。</li>
 <li>▶️ 使用 yt-dlp 自动归档视频。</li>
 <li>☑️ 支持批量操作。</li>
 <li>🔐 支持 SSO 单点登录。</li>
 <li>🌙 深色模式。</li>
 <li>💾 优先支持自托管。</li>
 <li>⬇️ 从 Chrome、Pocket、Linkwarden、Omnivore、Tab Session Manager 导入书签。</li>
 <li>🔄 通过 floccus 与浏览器书签自动同步。</li>
 <li>[计划中] 移动端离线阅读、书签语义搜索，……</li>
</ul>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094930-1.webp&amp;size=m" alt="6fb0d16e6fa436a7fceaa95125fee34d.png"></p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方 GitHub 地址：<a href="https://github.com/karakeep-app/karakeep">https://github.com/karakeep-app/karakeep</a> （目前 21.1k 个 star，欢迎大家去给项目点星星！）</p>
<p>Demo 地址：<a href="https://try.karakeep.app/signin">https://try.karakeep.app</a></p>
<p>默认账号密码：</p>
<p>Email: <code>demo@karakeep.app</code></p>
<p>Password: <code>demodemo</code></p>
<p>当然如果你体验完还想自己用 docker 搭建一个，那我们就继续往下！</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的 <a href="http://gao.ee/lca">莱卡云服务器</a>，建议服务器内存 1G 以上，当然你也可以选择其他 <a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩周补充-----">5. 搭建视频（过俩周补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/karakeep

cd /root/data/docker_data/karakeep
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  web:
    image: ghcr.io/karakeep-app/karakeep:latest
    restart: unless-stopped
    volumes:
      # By default, the data is stored in a docker volume called "data".
      # If you want to mount a custom directory, change the volume mapping to:
      # - /path/to/your/directory:/data
      - ./data:/data
    ports:
      - 3030:3000
    env_file:
      - .env
    environment:
      MEILI_ADDR: http://meilisearch:7700
      BROWSER_WEB_URL: http://chrome:9222
      # OPENAI_API_KEY: ...

      # You almost never want to change the value of the DATA_DIR variable.
      # If you want to mount a custom directory, change the volume mapping above instead.
      DATA_DIR: /data # DON'T CHANGE THIS
  chrome:
    image: gcr.io/zenika-hub/alpine-chrome:124
    restart: unless-stopped
    command:
      - --no-sandbox
      - --disable-gpu
      - --disable-dev-shm-usage
      - --remote-debugging-address=0.0.0.0
      - --remote-debugging-port=9222
      - --hide-scrollbars
  meilisearch:
    image: getmeili/meilisearch:v1.13.3
    restart: unless-stopped
    env_file:
      - .env
    environment:
      MEILI_NO_ANALYTICS: "true"
    volumes:
      - ./meilisearch:/meili_data
</code></pre>
<p>其中的左边的<code>3030</code>可以改成服务器上没有用过的端口，如果要用到AI功能的话，可以取消<code>OPENAI_API_KEY</code>的注释，填入自己的密钥。</p>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<p>接着我们来编辑下<code>.env</code></p>
<pre><code class="language-bash">cd /root/data/docker_data/karakeep
vim .env
</code></pre>
<p>粘贴如下内容：</p>
<pre><code class="language-env">KARAKEEP_VERSION=release
NEXTAUTH_SECRET=super_random_string
MEILI_MASTER_KEY=another_random_string
NEXTAUTH_URL=http://localhost:3000
</code></pre>
<ul>
 <li>其中的<code>http://localhost:3000</code>这个改成你自己之后用域名访问的地址，比如我的<code>https://karakeep.gugu.ovh</code></li>
 <li>其中的<code>super_random_string</code>和<code>another_random_string</code>需要我们自己生成。</li>
</ul>
<p>我们可以先在命令行里面输入</p>
<pre><code class="language-bash">openssl rand -base64 36
</code></pre>
<p>生成随机的字符，然后替代它们。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094926-1.webp&amp;size=m" alt="aebf462264a0d4c95fa1416bee41830a.png" style="zoom:50%;">
<p>我需要放在<code>.env</code>里的内容就是：</p>
<pre><code class="language-env">KARAKEEP_VERSION=release
NEXTAUTH_SECRET=Lu4YuG5pXji2/QB6blXaoWnfK2WdtKifPhEBt0UQCHqkxCAe
MEILI_MASTER_KEY=wJ222cTFWJ0/9Jnu38gU9Wb+AdCk2SBmQ687MdTbxT8c/V0b
NEXTAUTH_URL=https://karakeep.gugu.ovh
</code></pre>
<p>修改完成之后，同样的，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3030</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3030  #查看 3030 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-karakeep">6.4 启动 karakeep</h3>
<pre><code>cd /root/data/docker_data/karakeep

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3030</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！既然是加密的项目，不能用 http 使用明文传输，我们部署在公网一定要考虑使用反向代理工具配置 SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo 上 6 位数字的 xyz 续费永远都是 0.99 美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094916-1.webp&amp;size=m" alt="8a522c57d08898256ce3814d5183f811.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094914-1.webp&amp;size=m" alt="deeedad5afbbcc25441ac1a41e89ba31.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094909-1.webp&amp;size=m" alt="cf5928e754752471d09460cd31fb2eae.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094905-1.webp&amp;size=m" alt="832a857e518a6999f692c56a1b0d6d18.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094900-1.webp&amp;size=m" alt="bd08eed12b655993b53b6df83bcb6606.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094853-1.webp&amp;size=m" alt="ec68bb8adeb0d9661917ba2e77032906.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3030</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 karakeep 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 karakeep 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3030/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，所见即所得。</p>
<p>登录，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F100639-1.webp&amp;size=m" alt="32cb2fe6c8694197a931f84b06e6931d.png" style="zoom:33%;">
<p>首先注册一个账号，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F100634-1.webp&amp;size=m" alt="e04dc92bb6e9435aaebfc5d43eb4f56f.png" style="zoom: 33%;">
<p>后台页面，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094841-1.webp&amp;size=m" alt="2069ec87e83c0c1ad747046940e44717.png"></p>
<p>用户设置，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094838-1.webp&amp;size=m" alt="213472f4fcb8caa51ae8344d98424a60.png" style="zoom:50%;">
<p>如果觉得英文不习惯，也可以改成中文，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094833-1.webp&amp;size=m" alt="0cfd2e99f9d8a159389de1d0f8b3f163.png"></p>
<p>输入一个网址，测试一下，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094832-1.webp&amp;size=m" alt="2d1764ecbf9c5ff13e0692864d15659b.png"></p>
<p>支持给你存下来的网页打标签，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F101102.webp&amp;size=m" alt="58b7e0e99d814b62bfa15217b140b3a4.png"></p>
<p>服务器统计情况，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094827-1.webp&amp;size=m" alt="abe96ef7a5a74c3d3cd8330ec85073c2.png"></p>
<p>Karakeep是支持浏览器插件的，这边可以直接下载浏览器插件，方便浏览网页的时候使用，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F100541-1.webp&amp;size=m" alt="c5519d815ece46e7a66ebf39b763ec26.png"></p>
<p>输入你搭建好的域名，然后登录即可，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094824-1.webp&amp;size=m" alt="ccd39153c2f87d5ae8be6ee098cfbf7c.png" style="zoom:50%;">
<p>使用</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094817-1.webp&amp;size=m" alt="ea1377f2cd994631248c61114a911c92.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F094815-1.webp&amp;size=m" alt="c89e80bfa4ab4a3de5f1e1b7e6c11124.png"></p>
<p>也支持下载完整页面，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F11%2F13%2F101018.webp&amp;size=m" alt="502f8bd34f6f45f8af5ad101bd17bd69.png"></p>
<p>还有一些AI功能，大家可以自行探索。或者查看<a href="https://docs.karakeep.app/">Karakeep的官方文档</a></p>
<h3 id="8-1-更新-karakeep">8.1 更新 karakeep</h3>
<p>这个项目后续会持续有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/karakeep

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-karakeep">8.2 卸载 karakeep</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/karakeep

docker compose down

cd ..

rm -rf /root/data/docker_data/karakeep  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--使用简介">9. 使用简介</h2>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/karakeep-app/karakeep/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/karakeep-app/karakeep">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者 <a href="https://github.com/karakeep-app/karakeep">@civilblur</a> 的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star。</p>
<h2 id="参考资料">参考资料</h2>
<p>官方 GitHub：<a href="https://github.com/karakeep-app/karakeep">https://github.com/karakeep-app/karakeep</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-karakeep</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Thu, 13 Nov 2025 01:55:12 GMT</pubDate></item><item><title><![CDATA[十分钟搭建一次性私密信息共享平台——OTS｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-ots</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E6%AC%A1%E6%80%A7%E7%A7%81%E5%AF%86%E4%BF%A1%E6%81%AF%E5%85%B1%E4%BA%AB%E5%B9%B3%E5%8F%B0%E2%80%94%E2%80%94OTS%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-ots" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>好久没更新了，这周来和大家分享一个阅后即焚工具，安全高效的一次性私密信息共享平台——OTS（One-Time-Secret）</p>
<h2 id="2--OTS-简介">2. OTS 简介</h2>
<p>OTS 是一个一次性私密信息分享平台。私密信息在发送到服务器之前，会在浏览器中使用对称的 256 位 AES 加密进行加密。之后会生成一个包含私密信息的 ID 和密码的 URL。密码永远不会发送到服务器，因此服务器无法以合理的方式解密它所传递的私密信息。此外，私密信息在第一次读取后会立即被删除。</p>
<p><strong>功能</strong></p>
<ul>
 <li>私密信息在浏览器中通过 AES 256 位加密进行加密</li>
 <li>服务器永远不会接收到明文私密信息</li>
 <li>私密信息在第一次读取后即被删除</li>
</ul>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104028-1.webp&amp;size=m" alt="1fda6d3277a6b618383e3f5d09ecc446.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104055-1.webp&amp;size=m" alt="c25e783b58219bbb18541bb45c1688e9.png"></p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方 GitHub 地址：<a href="https://github.com/Luzifer/ots">https://github.com/Luzifer/ots</a> （目前 638 个 star，欢迎大家去给项目点星星！）</p>
<p>Demo 地址：<a href="https://ots.fyi/">https://ots.fyi/</a></p>
<p>当然如果你看到这边还想自己用 docker 搭建一个，那我们就继续往下！</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的 <a href="http://gao.ee/lca">莱卡云服务器</a>，建议服务器内存 1G 以上，当然你也可以选择其他 <a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/OTS

cd /root/data/docker_data/OTS
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  app:
    image: ghcr.io/luzifer/ots:latest
    container_name: ots-app
    restart: always
    ports:
      - 3003:3000
    environment:
      # Optional, see "Customization" in README
      #CUSTOMIZE: '/etc/ots/customize.yaml'
      # See README for details
      REDIS_URL: redis://redis:6379/0
      # 168h = 1w
      SECRET_EXPIRY: "604800"
      # "mem" or "redis" (See README)
      STORAGE_TYPE: redis
    depends_on:
      - redis

  redis:
    image: redis:latest
    container_name: ots-redis
    restart: always
    volumes:
      - ./data:/data
</code></pre>
<p>环境变量的说明如下：</p>
<table>
 <thead>
  <tr>
   <th>环境变量</th>
   <th>描述</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><code>REDIS_URL</code></td>
   <td><code>Redis</code> 数据库的连接字符串，格式为 <code>redis：//USR：PWD@HOST：PORT/DB</code>。用于指定 <code>OTS</code> 应用连接的 <code>Redis</code> 实例</td>
  </tr>
  <tr>
   <td><code>SECRET_EXPIRY</code></td>
   <td>秘密的过期时间，单位为秒（默认 <code>0</code> = 无过期）。此示例中设置为 <code>604800</code>（168 小时 = 1 周）</td>
  </tr>
  <tr>
   <td><code>STORAGE_TYPE</code></td>
   <td>用于指定存储类型，可以是 <code>mem</code>（内存存储）或 <code>redis</code>（使用 <code>Redis</code> 存储秘密）</td>
  </tr>
 </tbody>
</table>
<p>最后，在 <code>ots</code> 目录下执行以下命令一键启动：</p>
<p>其中的左边的<code>3003</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3003</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3003  #查看 3003 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-OTS">6.4 启动 OTS</h3>
<pre><code>cd /root/data/docker_data/OTS

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3003</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！既然是加密的项目，不能用 http 使用明文传输，我们部署在公网一定要考虑使用反向代理工具配置 SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo 上 6 位数字的 xyz 续费永远都是 0.99 美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104105-1.webp&amp;size=m" alt="08b09ee8604e6250e24354ccb4cd926b.png" style="zoom: 33%;">
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104137-1.webp&amp;size=m" alt="78186b53ea22c99caa737ec043e24947.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205949-1.webp&amp;size=m" alt="c2075b8e6a85bff585396fd4c0bca1ed.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104125-1.webp&amp;size=m" alt="525e20e0bea1448ff37e3d95dec2876c.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205935-1.webp&amp;size=m" alt="f5137b06b270769cc2ebca7019f47e35.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3003</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 OTS 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 OTS 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3003/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，所见即所得。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104117-1.webp&amp;size=m" alt="19f97b0b247033100477307b379bd7b8.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104115-1.webp&amp;size=m" alt="6e3f18b4fc5aeef1a5bdb998d4decf6e.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F10%2F22%2F104114-1.webp&amp;size=m" alt="ddd6171537aa47f30f150dfa9d9f8d6b.png"></p>
<h3 id="8-1-更新-OTS">8.1 更新 OTS</h3>
<p>这个项目后续会持续有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/OTS

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-OTS">8.2 卸载 OTS</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/OTS

docker compose down

cd ..

rm -rf /root/data/docker_data/OTS  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/Luzifer/ots/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/Luzifer/ots">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者 <a href="https://github.com/Luzifer/ots">@civilblur</a> 的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star。</p>
<h2 id="参考资料">参考资料</h2>
<p>官方 GitHub：<a href="https://github.com/Luzifer/ots">https://github.com/Luzifer/ots</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-ots</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Wed, 22 Oct 2025 03:04:21 GMT</pubDate></item><item><title><![CDATA[3分钟利用 Paypal 领取免费一年 Perplexity 会员！ 解锁AI搜索神器！网页点点就行！]]></title><link>https://blog.laoda.de/archives/paypal-perplexity-subscription</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=3%E5%88%86%E9%92%9F%E5%88%A9%E7%94%A8%20Paypal%20%E9%A2%86%E5%8F%96%E5%85%8D%E8%B4%B9%E4%B8%80%E5%B9%B4%20Perplexity%20%E4%BC%9A%E5%91%98%EF%BC%81%20%E8%A7%A3%E9%94%81AI%E6%90%9C%E7%B4%A2%E7%A5%9E%E5%99%A8%EF%BC%81%E7%BD%91%E9%A1%B5%E7%82%B9%E7%82%B9%E5%B0%B1%E8%A1%8C%EF%BC%81&amp;url=/archives/paypal-perplexity-subscription" width="1" height="1" alt="" style="opacity:0;">
<h3 id="简介">简介</h3>
<h4 id="Perplexity是什么-"><strong>Perplexity是什么？</strong></h4>
<p>Perplexity 是一个结合了 AI 聊天机器人和搜索引擎功能的工具，旨在快速提供准确、简洁的答案，并附上可靠的来源引用。它通过理解用户问题，从网络上实时抓取信息，整理成清晰的回答，特别适合需要快速查资料或做研究的用户。</p>
<h4 id="Pro版本的功能-"><strong>Pro版本的功能：</strong></h4>
<p>Perplexity Pro 提供更高级的功能，收费20美元/月，功能包括：</p>
<ul>
 <li><strong>多模型选择</strong>：用户可切换使用 GPT-4o、Claude 3.7、Gemini Flash 等不同语言模型，灵活应对不同需求。</li>
 <li><strong>Pages报告生成</strong>：可根据用户需求生成定制化的精美简报，适合研究或商务用途。</li>
 <li><strong>高级搜索功能</strong>：如学术论文模式，专注搜索学术资源（如 Arxiv、SemanticScholar），提升研究效率。</li>
 <li><strong>更高使用额度</strong>：相比免费版，Pro 版支持更多查询次数和更复杂的任务。</li>
</ul>
<p>如果你需要快速查资料、做研究或验证信息，Perplexity 是最佳选择，尤其适合学术和专业场景。</p>
<h3 id="领取条件">领取条件</h3>
<ul>
 <li>1个PayPal账号（我用的是美区，据网友测试国区也可以）</li>
 <li>能访问真正的互联网</li>
 <li>Perplexity 账号（可以现场注册）</li>
</ul>
<h3 id="领取方式">领取方式</h3>
<p>领取地址：<a href="https://www.perplexity.ai/join/p/paypal-subscription">https://www.perplexity.ai/join/p/paypal-subscription</a></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182400-1.webp&amp;size=m" alt="ca3e75602a808c3b92397198da35363b.png"></p>
<p>链接PayPal，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182357-1.webp&amp;size=m" alt="b4718b6f264d1c7de5207d0b5b7f9e34.png"></p>
<p>我这边登录的是美区的PayPal，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182356-1.webp&amp;size=m" alt="a1f67cdf27b91ba2458beef66f8cfa17.png"></p>
<p>选择接受优惠，
 <br>
 <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182353-1.webp&amp;size=m" alt="2f608f0e1364368ec38a54e434a4ac29.png"></p>
<p>成功领取！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182351-1.webp&amp;size=m" alt="7f1cf6733ecd5e65c02f165a6c8a1964.png"></p>
<p>已经可以正常使用了！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182350-1.webp&amp;size=m" alt="b12078649e490b14d6fee9c83be13f85.png"></p>
<p>如果担心被反薅，记得取消 Perplexity 自动续费订阅，</p>
<p>访问：<a href="https://www.perplexity.ai/join/p/paypal-subscription">https://www.perplexity.ai/account/details</a></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182348-1.webp&amp;size=m" alt="fa470b29a43e2a70b1eb49c74b2f6dcb.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182345-1.webp&amp;size=m" alt="a6afdd3b8f2a1095fdabd1ee7fe59c19.png"></p>
<p>取消订阅即可，不影响使用</p>
<p>同样的，Perplexity 还支持Mac桌面端，也可以用起来了！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F04%2F182348-1_1.webp&amp;size=m" alt="257164195481a94f33de0c5b62a87130.png"></p>
<h3 id="注意点">注意点</h3>
<ul>
 <li>这次似乎国区的PayPal也可以领取。</li>
 <li>有不少网友评价Perplexity玩不起，之前三星的泄漏的一年优惠码，没用几天被收回了。</li>
 <li>也有网友表示现在这次打开会提示开通过了。 You are already subscribed or have previously subscribed to Perplexity Pro.</li>
 <li>还有一些一注册上就风控，即使美区也是，原先注册好的死活都不让领说领过了，换无数个邮箱尝试依旧如此，这个时候可以考虑换一个干净的IP再试试。</li>
</ul>]]></description><guid isPermaLink="false">/archives/paypal-perplexity-subscription</guid><dc:creator>咕咕</dc:creator><category>有用的小知识</category><pubDate>Thu, 4 Sep 2025 10:31:06 GMT</pubDate></item><item><title><![CDATA[给你的Docker应用加一层保险！10分钟搭建一个简单好用的认证中间件—— Tinyauth]]></title><link>https://blog.laoda.de/archives/docker-compose-install-tinyauth</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E7%BB%99%E4%BD%A0%E7%9A%84Docker%E5%BA%94%E7%94%A8%E5%8A%A0%E4%B8%80%E5%B1%82%E4%BF%9D%E9%99%A9%EF%BC%8110%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E5%A5%BD%E7%94%A8%E7%9A%84%E8%AE%A4%E8%AF%81%E4%B8%AD%E9%97%B4%E4%BB%B6%E2%80%94%E2%80%94%20Tinyauth&amp;url=/archives/docker-compose-install-tinyauth" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>这两三年来，我们搭建了不少好玩的Docker应用，其实一直陆陆续续有小伙伴在视频评论区和博客的评论区询问，怎么样才能让我的Docker应用更安全一点？</p>
<p>这一期，我们就来介绍这样一个工具，用最简单的方式来给我们的Docker应用加一层保险！</p>
<p>效果展示：</p>
<p>保存之后。</p>
<p>再次打开简历这个网页。</p>
<p>提示需要登录了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161435-1.webp&amp;size=m" alt="ae23d63f56a62d74560f7997f8537212.png"></p>
<p>输入账号密码，继续</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161434-1.webp&amp;size=m" alt="9cb7f756e503807085b95ed778e742c8.png"></p>
<p>进来了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161417-1.webp&amp;size=m" alt="cd86b2609a4ec471929f0fbc4d43d825.png"></p>
<h2 id="2--Tinyauth简介">2. Tinyauth简介</h2>
<p>Tinyauth 是个简单好用的认证中间件，能给你的 Docker 应用加个简洁的登录页面，或者支持 Google、GitHub 以及其他平台的 OAuth 认证。它跟主流代理比如 Nginx Proxy Manager、Traefik、Nginx 和 Caddy 都能无缝配合。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161535-1.webp&amp;size=m" alt="355959a7fc641c514e84dc5272ba9893.png"></p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/steveiliop56/tinyauth">https://github.com/steveiliop56/tinyauth</a> (目前5.3K个star，欢迎大家去给项目点星星！）</p>
<p>文档地址：<a href="https://tinyauth.app/docs/guides/nginx-proxy-manager">https://tinyauth.app/docs/guides/nginx-proxy-manager</a></p>
<p>Demo地址：<a href="https://tinyauth.app/">https://tinyauth.app/</a></p>
<p>下面我们就用 Tinyauth配合 Nginx Proxy Manager，简单分享一下是怎么搭建这个中间件从而来保护我们的Docker应用的。</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：这边强烈建议用非大陆的服务器，咕咕这边用的香港的<a href="https://gao.ee/lca">莱卡云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<p>我们这边假设大家都装好了Nginx Proxy Manger，</p>
<p>假设Nginx Proxy Manger在服务器上的路径是<code>~/data/docker_data/npm</code></p>
<p>这边的话就只需要修改一下即可。</p>
<p>官方文档给的参考如下：</p>
<pre><code class="language-yaml">services:
  npm:
    container_name: npm
    image: jc21/nginx-proxy-manager:2
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 81:81
    volumes:
      - npm-data:/data
      - npm-letsencrypt:/etc/letsencrypt

  nginx:
    container_name: nginx
    image: nginx:latest
    restart: unless-stopped

  tinyauth:
    container_name: tinyauth
    image: ghcr.io/steveiliop56/tinyauth:v3
    restart: unless-stopped
    environment:
      - SECRET_FILE=/secret.txt
      - APP_URL=http://tinyauth.example.com
      - USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u # user:password

volumes:
  npm-data:
  npm-letsencrypt:
</code></pre>
<p>如果直接使用，你一定会遇到很多问题。</p>
<p>
 <del>我不会告诉你我用官方的这个配置文件，折腾了大半小时 = =</del>
</p>
<p>这边直接用咕咕修改过的这个：</p>
<p>重新编辑你的NPM的<code>docker-compose.yaml</code>文件，改成下面这个：</p>
<pre><code class="language-yaml">services:
  npm:
    container_name: npm
    image: jc21/nginx-proxy-manager:2
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 81:81
    volumes:
      - ./data:/data         # 冒号左边的 ./data改成你自己实际的路径
      - ./letsencrypt:/etc/letsencrypt  # 冒号左边的 ./letsencrypt改成你自己实际的路径

  tinyauth:
    container_name: tinyauth
    image: ghcr.io/steveiliop56/tinyauth:v3
    restart: unless-stopped
    environment:
      - SECRET=kX9mPqW3zT7rY2vN8bL4jF6hD1cA5eK2  # 这个也要修改
      - APP_URL=https://auth.gugu.ovh  #这个也要修改
      - USERS=roy:$$2a$$10$$oXMqgLV/S1hrknYQht.WYu7YfWxkI4VriQn/y # user:password 这边要修改
</code></pre>
<p>然后我们来看需要修改的部分。</p>
<p><code>SECRET</code>，这个的话，直接在命令行操作：</p>
<p>生成secret:</p>
<pre><code class="language-bash">openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32 &amp;&amp; echo
</code></pre>
<p>输出类似：<code>kX9mPqW3zT7rY2vN8bL4jF6hD1cA5eK2</code> 填入yaml即可。</p>
<p><code>APP_URL</code> 这里改成你的tinyauth将来想要使用的域名，比如我这边<code>https://auth.gugu.ovh</code></p>
<p><code>USERS</code> ，这个官方也提供了方法，生成用户名和密码。</p>
<pre><code class="language-bash">docker run -i -t --rm ghcr.io/steveiliop56/tinyauth:v3 user create --interactive
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161524-1.webp&amp;size=m" alt="6788be9f0dedebd6fa8cd177d5dfe651.png"></p>
<p>为docker格式化输出这个，记得选<code>yes</code>（按住shift再按小键盘方向键就可以选）</p>
<p>原因是USERS这边在yaml文件里要做哈希转换（比如哈希中的 <code>$</code> 需要正确转义为 <code>$$</code>，命令行的 Docker 格式会自动处理。），如果不格式化输出会有问题。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161522-1.webp&amp;size=m" alt="c60fa52194d0d7b685327187290f75de.png"></p>
<p>当然也支持多个用户，可以再打一遍代码，设置第二个用户，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161521-1.webp&amp;size=m" alt="595a1c77b1cc3807c6f4d398609c5c20.png"></p>
<p>如果是一个用户，我们直接贴到yaml文件里即可，但是如果像我们现在这样，有三个用户，直接放进yaml文件会有点长，而且也不好维护。</p>
<p>所以，我们可以把用户配置放入 <code>.env</code> 文件，可以这样做：</p>
<p>编辑 <code>~/data/docker_data/npm/.env</code>：</p>
<pre><code class="language-env">SECRET=kX9mPqW3zT7rY2vN8bL4jF6hD1cA5eK2
APP_URL=https://auth.gugu.ovh
USERS=roy:$$2a$$10$$oXMqgLV/S1hrknYQht.WYu7YfEjBdSB5rIicj23O8WxkI4VriQn/y,gugu:$$2a$$10$$s.nq/KZLBlFwUiSUNyRUGe0j2pp.A9/.tecuX7QsCBq242baKgKJ.,xixi:$$2a$$10$$6smj5Y/PD.jB1a2Z2gDAxOVnlcv8HfINtLrzCmmTjMZLObBwV8DoW
</code></pre>
<p>修改 <code>docker-compose.yaml</code> 以引用<code> .env</code>：</p>
<pre><code class="language-yaml">services:
  npm:
    container_name: npm
    image: jc21/nginx-proxy-manager:2
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 81:81
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

  nginx:
    container_name: nginx
    image: nginx:latest
    restart: unless-stopped

  tinyauth:
    container_name: tinyauth
    image: ghcr.io/steveiliop56/tinyauth:v3
    restart: unless-stopped
	env_file:
      - .env
#    environment:
#      - SECRET=kX9mPqW3zT7rY2vN8bL4jF6hD1cA5eK2
#      - APP_URL=https://auth.gugu.ovh
#      - USERS=roy:$$2a$$10$$oXMqgLV/S1hrknYQht.WYu7YfEjBdSB5rIicj23O8WxkI4VriQn/y # user:password
</code></pre>
<p>这样基本上就OK啦。</p>
<p>重新启动NPM</p>
<pre><code class="language-bash">cd ~/data/docker_data/npm

docker compose down 

docker compose up -d 

docker compose logs tinyauth
</code></pre>
<p>出现类似，代表成功。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161517-1.webp&amp;size=m" alt="d9f4bfbde7c1b712d735d834b0cffb87.png"></p>
<p>这边我们先搞一下反向代理！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-配置Tinyauth的反向代理">7.1 配置Tinyauth的反向代理</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161515-1.webp&amp;size=m" alt="343d7766a70c301276c8bfae52fae8e3.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161509-1.webp&amp;size=m" alt="aca0ebcc28a73586bb9c43131b0490cf.png" style="zoom:50%;">
<p>确保“阻止常见漏洞”(Bolck Common Exploits)选项是关掉的。如果这选项开了，Nginx 会把 URL 里的查询参数给拦下来，而 Tinyauth 得靠这些参数才能正常工作。</p>
<p><code>tinyauth</code>这个是容器的名字，因为它和NPM在一个网络下，所以可以用容器名字来代替域名，<code>3000</code>是内部的端口，保持即可不要更改。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161506-1.webp&amp;size=m" alt="8ecf402ef51f5a3ec7ca759a85ae647c.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161457-1.webp&amp;size=m" alt="48c4db84474ea229406a39104f965c33.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161454-1.webp&amp;size=m" alt="b1f1a1aec3c198cc06b60758a3fad1e5.png" style="zoom:50%;">
<p>然后访问域名就可以访问了！</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161450-1.webp&amp;size=m" alt="5c42cfa09961f64c36e18ea9d2ba4aeb.png" style="zoom:50%;">
<h3 id="7-2-配置需要保护的应用的反向代理">7.2 配置需要保护的应用的反向代理</h3>
<p>我这边以之前介绍的简历应用（<a href="https://blog.laoda.de/archives/docker-compose-install-magic-resume">让写简历变得简单且智能！十分钟搭建一个在线简历编辑器——Magic Resume｜好玩儿的Docker项目</a>）为例子，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161443-1.webp&amp;size=m" alt="084d9f5958a47f6b0e867f163ddc06de.png" style="zoom:50%;">
<p>找到你需要添加登录页的应用的对应的NPM配置，在Advance里面添加：</p>
<pre><code class="language-nginx"># Root location
location / {
  # Pass the request to the app
  proxy_pass          $forward_scheme://$server:$port;

  # Add other app specific config here

  # Tinyauth auth request
  auth_request /tinyauth;
  error_page 401 = @tinyauth_login;
}

# Tinyauth auth request
location /tinyauth {
  # Pass request to Tinyauth
  proxy_pass http://tinyauth:3000/api/auth/nginx;

  # Pass the request headers
  proxy_set_header x-forwarded-proto $scheme;
  proxy_set_header x-forwarded-host $http_host;
  proxy_set_header x-forwarded-uri $request_uri;
}

# Tinyauth login redirect
location @tinyauth_login {
  return 302 https://auth.gugu.ovh/login?redirect_uri=$scheme://$http_host$request_uri; # Make sure to replace the https://auth.gugu.ovh with your own app URL
}
</code></pre>
<p>其他地方都不用管，只要把<code>https://auth.gugu.ovh</code> 替换成你自己的tinyauth的域名即可。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161437-1.webp&amp;size=m" alt="75bde1737d7b3d2d605860bb839fa567.png" style="zoom: 50%;">
<p>保存之后。</p>
<p>再次打开简历这个网页。</p>
<p>提示需要登录了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161435-1.webp&amp;size=m" alt="ae23d63f56a62d74560f7997f8537212.png"></p>
<p>输入账号密码，继续</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161434-1.webp&amp;size=m" alt="9cb7f756e503807085b95ed778e742c8.png"></p>
<p>进来了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F09%2F03%2F161417-1.webp&amp;size=m" alt="cd86b2609a4ec471929f0fbc4d43d825.png"></p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>其他的也类似，只需要在对应应用的NPM的Advance里面加：</p>
<pre><code class="language-nginx"># Root location
location / {
  # Pass the request to the app
  proxy_pass          $forward_scheme://$server:$port;

  # Add other app specific config here

  # Tinyauth auth request
  auth_request /tinyauth;
  error_page 401 = @tinyauth_login;
}

# Tinyauth auth request
location /tinyauth {
  # Pass request to Tinyauth
  proxy_pass http://tinyauth:3000/api/auth/nginx;

  # Pass the request headers
  proxy_set_header x-forwarded-proto $scheme;
  proxy_set_header x-forwarded-host $http_host;
  proxy_set_header x-forwarded-uri $request_uri;
}

# Tinyauth login redirect
location @tinyauth_login {
  return 302 https://auth.gugu.ovh/login?redirect_uri=$scheme://$http_host$request_uri; # Make sure to replace the https://auth.gugu.ovh with your own app URL
}
</code></pre>
<p>即可。</p>
<p>PS: <code>/tinyauth</code> 这个路径可以随便改，指南里用这个名字只是为了方便。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/steveiliop56/tinyauth/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/steveiliop56/tinyauth">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者<a href="https://github.com/steveiliop56">@steveiliop56</a>的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star ⭐️</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/steveiliop56/tinyauth">https://github.com/steveiliop56/tinyauth</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-tinyauth</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Wed, 3 Sep 2025 08:30:34 GMT</pubDate></item><item><title><![CDATA[Dify本地部署上手攻略：轻松打造你的专属AI神器｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-dify</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=Dify%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2%E4%B8%8A%E6%89%8B%E6%94%BB%E7%95%A5%EF%BC%9A%E8%BD%BB%E6%9D%BE%E6%89%93%E9%80%A0%E4%BD%A0%E7%9A%84%E4%B8%93%E5%B1%9EAI%E7%A5%9E%E5%99%A8%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-dify" width="1" height="1" alt="" style="opacity:0;">
<h2 id="前言">前言</h2>
<p>Dify是一个开源的AI应用开发平台，简单来说，它能让普通人也能轻松创建智能聊天机器人或AI助手。</p>
<p>它通过拖拽式的界面，整合了各种大语言模型和工具，比如可以连接企业知识库或外部API，让AI能回答专业问题或完成复杂任务。无论是程序员还是非技术人员，都能用它快速搭建AI应用，省时省力。Dify还支持本地部署，数据安全有保障，特别适合想快速上手AI的团队或个人。</p>
<p>其实Dify已经火了有很长时间了，之前嫌麻烦，我一直没怎么用。最近，公司里的一批小伙伴都换了配置更高的新电脑，纷纷在本地部署起了Dify，这一期就来一个小白级别的教程，和大家简单分享一下Dify的本地部署。</p>
<h2 id="准备工作">准备工作</h2>
<p>Dify本身官方对电脑硬件的建议要求是：</p>
<ul>
 <li>CPU &gt;= 2 Core</li>
 <li>RAM &gt;= 4 GiB</li>
</ul>
<p>如果你打算做完全本地的部署，即不用云端的大模型，</p>
<p>如果你是windows电脑，建议配置如下：</p>
<p><strong>内存</strong>：至少 16GB 系统内存（推荐 24GB 以上，留 8GB 给操作系统和其他软件）。</p>
<p><strong>GPU</strong>（可选但推荐）：至少 16GB VRAM 的 GPU（如 AMD Radeon RX 9070 XT 或 NVIDIA RTX 3090），支持 MXFP4 量化。GPU 内存带宽需高（如 GDDR6X/GDDR7，1000+ GB/s）。</p>
<p><strong>CPU</strong>：支持 CPU 推理，但速度较慢。推荐高性能 CPU（如 AMD Ryzen 9 5900X 或 Intel Core i9）。</p>
<p>如果是Mac的话，</p>
<p><strong>硬件</strong>：Apple Silicon（M1/M2/M3/M4），至少 16GB 统一内存（推荐 32GB）。</p>
<p>我自己这边用的是Mac，部署起来相对简单一些，用Windows的小伙伴可能会稍微复杂一丢丢。</p>
<p>Windows安装Docker可以参考这个：https://docs.docker.com/desktop/windows/install/#wsl-2-backend</p>
<p><strong>本质都是先在本地电脑安装好Docker，然后通过Docker来部署Dify。</strong></p>
<h2 id="安装Docker">安装Docker</h2>
<p>本地装docker，可以去docker官网直接下载一个安装包。</p>
<p>官方地址：<code>https://www.docker.com/products/docker-desktop/</code></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160558-1.webp&amp;size=m" alt="img"></p>
<p>下载之后，就像安装普通软件一样，安装一下。</p>
<p>然后打开docker。</p>
<p>打开Mac的终端，输入<code>docker -v</code>，有版本号说明安装好了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160555-1.webp&amp;size=m" alt="img"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160553-1.webp&amp;size=m" alt="img"></p>
<p>这边还会涉及docker换源，由于防火墙的原因，我们大陆可能无法访问docker的镜像仓库，建议大家换成中科大的源:<code>https://docker.mirrors.ustc.edu.cn/</code></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160551-1.webp&amp;size=m" alt="img"></p>
<p>改成这个：</p>
<pre><code>{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "features": {
    "buildkit": true
  },
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn"
  ]
}
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160545-1.webp&amp;size=m" alt="img"></p>
<p>然后记得点击应用并重启。</p>
<p>使用如下命令查看Docker配置，</p>
<pre><code class="language-bash">docker info
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160540-1.webp&amp;size=m" alt="3c158daac7e908df23db4bede4f8db8d.png"></p>
<p>就可以了。</p>
<h2 id="安装Dify">安装Dify</h2>
<p>Docker安装好之后，接下来安装我们今天的主角——Dify。</p>
<p>文档地址：<code>https://docs.dify.ai/en/introduction</code></p>
<p>这边一直关注咕咕的小伙伴可以很轻松的安装好。</p>
<p>Mac和Linux其实差不多，我们直接像操作VPS一样来就行。</p>
<pre><code class="language-bash">mkdir ./data/docker_data
cd data/docker_data
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160529-1.webp&amp;size=m" alt="img"></p>
<pre><code class="language-bash">git clone --branch "$(curl -s https://api.github.com/repos/langgenius/dify/releases/latest | jq -r .tag_name)" https://github.com/langgenius/dify.git      # 从GitHub下载dify源码

cd dify/docker    # 进入文件夹

cp .env.example .env    # 拷贝一份配置文件
</code></pre>
<p>这里如果后续有需求，可以自行修改这个配置文件，一起来看一下</p>
<pre><code class="language-env"># ------------------------------
# Environment Variables for API service &amp; worker
# ------------------------------

# ------------------------------
# Common Variables
# ------------------------------

# The backend URL of the console API,
# used to concatenate the authorization callback.
# If empty, it is the same domain.
# Example: https://api.console.dify.ai
CONSOLE_API_URL=

# The front-end URL of the console web,
# used to concatenate some front-end addresses and for CORS configuration use.
# If empty, it is the same domain.
# Example: https://console.dify.ai
CONSOLE_WEB_URL=

# Service API Url,
# used to display Service API Base Url to the front-end.
# If empty, it is the same domain.
# Example: https://api.dify.ai
SERVICE_API_URL=

# WebApp API backend Url,
# used to declare the back-end URL for the front-end API.
# If empty, it is the same domain.
# Example: https://api.app.dify.ai
APP_API_URL=

# WebApp Url,
# used to display WebAPP API Base Url to the front-end.
# If empty, it is the same domain.
# Example: https://app.dify.ai
APP_WEB_URL=

# File preview or download Url prefix.
# used to display File preview or download Url to the front-end or as Multi-model inputs;
# Url is signed and has expiration time.
# Setting FILES_URL is required for file processing plugins.
#   - For https://example.com, use FILES_URL=https://example.com
#   - For http://example.com, use FILES_URL=http://example.com
#   Recommendation: use a dedicated domain (e.g., https://upload.example.com).
#   Alternatively, use http://&lt;your-ip&gt;:5001 or http://api:5001,
#   ensuring port 5001 is externally accessible (see docker-compose.yaml).
FILES_URL=

# INTERNAL_FILES_URL is used for plugin daemon communication within Docker network.
# Set this to the internal Docker service URL for proper plugin file access.
# Example: INTERNAL_FILES_URL=http://api:5001
INTERNAL_FILES_URL=

# Ensure UTF-8 encoding
LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
PYTHONIOENCODING=utf-8

# ------------------------------
# Server Configuration
# ------------------------------

# The log level for the application.
# Supported values are `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
LOG_LEVEL=INFO
# Log file path
LOG_FILE=/app/logs/server.log
# Log file max size, the unit is MB
LOG_FILE_MAX_SIZE=20
# Log file max backup count
LOG_FILE_BACKUP_COUNT=5
# Log dateformat
LOG_DATEFORMAT=%Y-%m-%d %H:%M:%S
# Log Timezone
LOG_TZ=UTC

# Debug mode, default is false.
# It is recommended to turn on this configuration for local development
# to prevent some problems caused by monkey patch.
DEBUG=false

# Flask debug mode, it can output trace information at the interface when turned on,
# which is convenient for debugging.
FLASK_DEBUG=false

# Enable request logging, which will log the request and response information.
# And the log level is DEBUG
ENABLE_REQUEST_LOGGING=False

# A secret key that is used for securely signing the session cookie
# and encrypting sensitive information on the database.
# You can generate a strong key using `openssl rand -base64 42`.
SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U

# Password for admin user initialization.
# If left unset, admin user will not be prompted for a password
# when creating the initial admin account.
# The length of the password cannot exceed 30 characters.
INIT_PASSWORD=

# Deployment environment.
# Supported values are `PRODUCTION`, `TESTING`. Default is `PRODUCTION`.
# Testing environment. There will be a distinct color label on the front-end page,
# indicating that this environment is a testing environment.
DEPLOY_ENV=PRODUCTION

# Whether to enable the version check policy.
# If set to empty, https://updates.dify.ai will be called for version check.
CHECK_UPDATE_URL=https://updates.dify.ai

# Used to change the OpenAI base address, default is https://api.openai.com/v1.
# When OpenAI cannot be accessed in China, replace it with a domestic mirror address,
# or when a local model provides OpenAI compatible API, it can be replaced.
OPENAI_API_BASE=https://api.openai.com/v1

# When enabled, migrations will be executed prior to application startup
# and the application will start after the migrations have completed.
MIGRATION_ENABLED=true

# File Access Time specifies a time interval in seconds for the file to be accessed.
# The default value is 300 seconds.
FILES_ACCESS_TIMEOUT=300

# Access token expiration time in minutes
ACCESS_TOKEN_EXPIRE_MINUTES=60

# Refresh token expiration time in days
REFRESH_TOKEN_EXPIRE_DAYS=30

# The maximum number of active requests for the application, where 0 means unlimited, should be a non-negative integer.
APP_MAX_ACTIVE_REQUESTS=0
APP_MAX_EXECUTION_TIME=1200

# ------------------------------
# Container Startup Related Configuration
# Only effective when starting with docker image or docker-compose.
# ------------------------------

# API service binding address, default: 0.0.0.0, i.e., all addresses can be accessed.
DIFY_BIND_ADDRESS=0.0.0.0

# API service binding port number, default 5001.
DIFY_PORT=5001

# The number of API server workers, i.e., the number of workers.
# Formula: number of cpu cores x 2 + 1 for sync, 1 for Gevent
# Reference: https://docs.gunicorn.org/en/stable/design.html#how-many-workers
SERVER_WORKER_AMOUNT=1

# Defaults to gevent. If using windows, it can be switched to sync or solo.
SERVER_WORKER_CLASS=gevent

# Default number of worker connections, the default is 10.
SERVER_WORKER_CONNECTIONS=10

# Similar to SERVER_WORKER_CLASS.
# If using windows, it can be switched to sync or solo.
CELERY_WORKER_CLASS=

# Request handling timeout. The default is 200,
# it is recommended to set it to 360 to support a longer sse connection time.
GUNICORN_TIMEOUT=360

# The number of Celery workers. The default is 1, and can be set as needed.
CELERY_WORKER_AMOUNT=

# Flag indicating whether to enable autoscaling of Celery workers.
#
# Autoscaling is useful when tasks are CPU intensive and can be dynamically
# allocated and deallocated based on the workload.
#
# When autoscaling is enabled, the maximum and minimum number of workers can
# be specified. The autoscaling algorithm will dynamically adjust the number
# of workers within the specified range.
#
# Default is false (i.e., autoscaling is disabled).
#
# Example:
# CELERY_AUTO_SCALE=true
CELERY_AUTO_SCALE=false

# The maximum number of Celery workers that can be autoscaled.
# This is optional and only used when autoscaling is enabled.
# Default is not set.
CELERY_MAX_WORKERS=

# The minimum number of Celery workers that can be autoscaled.
# This is optional and only used when autoscaling is enabled.
# Default is not set.
CELERY_MIN_WORKERS=

# API Tool configuration
API_TOOL_DEFAULT_CONNECT_TIMEOUT=10
API_TOOL_DEFAULT_READ_TIMEOUT=60

# -------------------------------
# Datasource Configuration
# --------------------------------
ENABLE_WEBSITE_JINAREADER=true
ENABLE_WEBSITE_FIRECRAWL=true
ENABLE_WEBSITE_WATERCRAWL=true

# ------------------------------
# Database Configuration
# The database uses PostgreSQL. Please use the public schema.
# It is consistent with the configuration in the 'db' service below.
# ------------------------------

DB_USERNAME=postgres
DB_PASSWORD=difyai123456
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify
# The size of the database connection pool.
# The default is 30 connections, which can be appropriately increased.
SQLALCHEMY_POOL_SIZE=30
# The default is 10 connections, which allows temporary overflow beyond the pool size.
SQLALCHEMY_MAX_OVERFLOW=10
# Database connection pool recycling time, the default is 3600 seconds.
SQLALCHEMY_POOL_RECYCLE=3600
# Whether to print SQL, default is false.
SQLALCHEMY_ECHO=false
# If True, will test connections for liveness upon each checkout
SQLALCHEMY_POOL_PRE_PING=false
# Whether to enable the Last in first out option or use default FIFO queue if is false
SQLALCHEMY_POOL_USE_LIFO=false

# Maximum number of connections to the database
# Default is 100
#
# Reference: https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-MAX-CONNECTIONS
POSTGRES_MAX_CONNECTIONS=100

# Sets the amount of shared memory used for postgres's shared buffers.
# Default is 128MB
# Recommended value: 25% of available memory
# Reference: https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-SHARED-BUFFERS
POSTGRES_SHARED_BUFFERS=128MB

# Sets the amount of memory used by each database worker for working space.
# Default is 4MB
#
# Reference: https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM
POSTGRES_WORK_MEM=4MB

# Sets the amount of memory reserved for maintenance activities.
# Default is 64MB
#
# Reference: https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM
POSTGRES_MAINTENANCE_WORK_MEM=64MB

# Sets the planner's assumption about the effective cache size.
# Default is 4096MB
#
# Reference: https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE
POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB

# ------------------------------
# Redis Configuration
# This Redis configuration is used for caching and for pub/sub during conversation.
# ------------------------------

REDIS_HOST=redis
REDIS_PORT=6379
REDIS_USERNAME=
REDIS_PASSWORD=difyai123456
REDIS_USE_SSL=false
# SSL configuration for Redis (when REDIS_USE_SSL=true)
REDIS_SSL_CERT_REQS=CERT_NONE
# Options: CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
REDIS_SSL_CA_CERTS=
# Path to CA certificate file for SSL verification
REDIS_SSL_CERTFILE=
# Path to client certificate file for SSL authentication
REDIS_SSL_KEYFILE=
# Path to client private key file for SSL authentication
REDIS_DB=0

# Whether to use Redis Sentinel mode.
# If set to true, the application will automatically discover and connect to the master node through Sentinel.
REDIS_USE_SENTINEL=false

# List of Redis Sentinel nodes. If Sentinel mode is enabled, provide at least one Sentinel IP and port.
# Format: `&lt;sentinel1_ip&gt;:&lt;sentinel1_port&gt;,&lt;sentinel2_ip&gt;:&lt;sentinel2_port&gt;,&lt;sentinel3_ip&gt;:&lt;sentinel3_port&gt;`
REDIS_SENTINELS=
REDIS_SENTINEL_SERVICE_NAME=
REDIS_SENTINEL_USERNAME=
REDIS_SENTINEL_PASSWORD=
REDIS_SENTINEL_SOCKET_TIMEOUT=0.1

# List of Redis Cluster nodes. If Cluster mode is enabled, provide at least one Cluster IP and port.
# Format: `&lt;Cluster1_ip&gt;:&lt;Cluster1_port&gt;,&lt;Cluster2_ip&gt;:&lt;Cluster2_port&gt;,&lt;Cluster3_ip&gt;:&lt;Cluster3_port&gt;`
REDIS_USE_CLUSTERS=false
REDIS_CLUSTERS=
REDIS_CLUSTERS_PASSWORD=

# ------------------------------
# Celery Configuration
# ------------------------------

# Use standalone redis as the broker, and redis db 1 for celery broker. (redis_username is usually set by defualt as empty)
# Format as follows: `redis://&lt;redis_username&gt;:&lt;redis_password&gt;@&lt;redis_host&gt;:&lt;redis_port&gt;/&lt;redis_database&gt;`.
# Example: redis://:difyai123456@redis:6379/1
# If use Redis Sentinel, format as follows: `sentinel://&lt;redis_username&gt;:&lt;redis_password&gt;@&lt;sentinel_host1&gt;:&lt;sentinel_port&gt;/&lt;redis_database&gt;`
# For high availability, you can configure multiple Sentinel nodes (if provided) separated by semicolons like below example:
# Example: sentinel://:difyai123456@localhost:26379/1;sentinel://:difyai12345@localhost:26379/1;sentinel://:difyai12345@localhost:26379/1
CELERY_BROKER_URL=redis://:difyai123456@redis:6379/1
CELERY_BACKEND=redis
BROKER_USE_SSL=false

# If you are using Redis Sentinel for high availability, configure the following settings.
CELERY_USE_SENTINEL=false
CELERY_SENTINEL_MASTER_NAME=
CELERY_SENTINEL_PASSWORD=
CELERY_SENTINEL_SOCKET_TIMEOUT=0.1

# ------------------------------
# CORS Configuration
# Used to set the front-end cross-domain access policy.
# ------------------------------

# Specifies the allowed origins for cross-origin requests to the Web API,
# e.g. https://dify.app or * for all origins.
WEB_API_CORS_ALLOW_ORIGINS=*

# Specifies the allowed origins for cross-origin requests to the console API,
# e.g. https://cloud.dify.ai or * for all origins.
CONSOLE_CORS_ALLOW_ORIGINS=*

# ------------------------------
# File Storage Configuration
# ------------------------------

# The type of storage to use for storing user files.
STORAGE_TYPE=opendal

# Apache OpenDAL Configuration
# The configuration for OpenDAL consists of the following format: OPENDAL_&lt;SCHEME_NAME&gt;_&lt;CONFIG_NAME&gt;.
# You can find all the service configurations (CONFIG_NAME) in the repository at: https://github.com/apache/opendal/tree/main/core/src/services.
# Dify will scan configurations starting with OPENDAL_&lt;SCHEME_NAME&gt; and automatically apply them.
# The scheme name for the OpenDAL storage.
OPENDAL_SCHEME=fs
# Configurations for OpenDAL Local File System.
OPENDAL_FS_ROOT=storage

# ClickZetta Volume Configuration (for storage backend)
# To use ClickZetta Volume as storage backend, set STORAGE_TYPE=clickzetta-volume
# Note: ClickZetta Volume will reuse the existing CLICKZETTA_* connection parameters

# Volume type selection (three types available):
# - user: Personal/small team use, simple config, user-level permissions
# - table: Enterprise multi-tenant, smart routing, table-level + user-level permissions
# - external: Data lake integration, external storage connection, volume-level + storage-level permissions
CLICKZETTA_VOLUME_TYPE=user

# External Volume name (required only when TYPE=external)
CLICKZETTA_VOLUME_NAME=

# Table Volume table prefix (used only when TYPE=table)
CLICKZETTA_VOLUME_TABLE_PREFIX=dataset_

# Dify file directory prefix (isolates from other apps, recommended to keep default)
CLICKZETTA_VOLUME_DIFY_PREFIX=dify_km

# S3 Configuration
#
S3_ENDPOINT=
S3_REGION=us-east-1
S3_BUCKET_NAME=difyai
S3_ACCESS_KEY=
S3_SECRET_KEY=
# Whether to use AWS managed IAM roles for authenticating with the S3 service.
# If set to false, the access key and secret key must be provided.
S3_USE_AWS_MANAGED_IAM=false

# Azure Blob Configuration
#
AZURE_BLOB_ACCOUNT_NAME=difyai
AZURE_BLOB_ACCOUNT_KEY=difyai
AZURE_BLOB_CONTAINER_NAME=difyai-container
AZURE_BLOB_ACCOUNT_URL=https://&lt;your_account_name&gt;.blob.core.windows.net

# Google Storage Configuration
#
GOOGLE_STORAGE_BUCKET_NAME=your-bucket-name
GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64=

# The Alibaba Cloud OSS configurations,
#
ALIYUN_OSS_BUCKET_NAME=your-bucket-name
ALIYUN_OSS_ACCESS_KEY=your-access-key
ALIYUN_OSS_SECRET_KEY=your-secret-key
ALIYUN_OSS_ENDPOINT=https://oss-ap-southeast-1-internal.aliyuncs.com
ALIYUN_OSS_REGION=ap-southeast-1
ALIYUN_OSS_AUTH_VERSION=v4
# Don't start with '/'. OSS doesn't support leading slash in object names.
ALIYUN_OSS_PATH=your-path

# Tencent COS Configuration
#
TENCENT_COS_BUCKET_NAME=your-bucket-name
TENCENT_COS_SECRET_KEY=your-secret-key
TENCENT_COS_SECRET_ID=your-secret-id
TENCENT_COS_REGION=your-region
TENCENT_COS_SCHEME=your-scheme

# Oracle Storage Configuration
#
OCI_ENDPOINT=https://your-object-storage-namespace.compat.objectstorage.us-ashburn-1.oraclecloud.com
OCI_BUCKET_NAME=your-bucket-name
OCI_ACCESS_KEY=your-access-key
OCI_SECRET_KEY=your-secret-key
OCI_REGION=us-ashburn-1

# Huawei OBS Configuration
#
HUAWEI_OBS_BUCKET_NAME=your-bucket-name
HUAWEI_OBS_SECRET_KEY=your-secret-key
HUAWEI_OBS_ACCESS_KEY=your-access-key
HUAWEI_OBS_SERVER=your-server-url

# Volcengine TOS Configuration
#
VOLCENGINE_TOS_BUCKET_NAME=your-bucket-name
VOLCENGINE_TOS_SECRET_KEY=your-secret-key
VOLCENGINE_TOS_ACCESS_KEY=your-access-key
VOLCENGINE_TOS_ENDPOINT=your-server-url
VOLCENGINE_TOS_REGION=your-region

# Baidu OBS Storage Configuration
#
BAIDU_OBS_BUCKET_NAME=your-bucket-name
BAIDU_OBS_SECRET_KEY=your-secret-key
BAIDU_OBS_ACCESS_KEY=your-access-key
BAIDU_OBS_ENDPOINT=your-server-url

# Supabase Storage Configuration
#
SUPABASE_BUCKET_NAME=your-bucket-name
SUPABASE_API_KEY=your-access-key
SUPABASE_URL=your-server-url

# ------------------------------
# Vector Database Configuration
# ------------------------------

# The type of vector store to use.
# Supported values are `weaviate`, `qdrant`, `milvus`, `myscale`, `relyt`, `pgvector`, `pgvecto-rs`, `chroma`, `opensearch`, `oracle`, `tencent`, `elasticsearch`, `elasticsearch-ja`, `analyticdb`, `couchbase`, `vikingdb`, `oceanbase`, `opengauss`, `tablestore`,`vastbase`,`tidb`,`tidb_on_qdrant`,`baidu`,`lindorm`,`huawei_cloud`,`upstash`, `matrixone`, `clickzetta`.
VECTOR_STORE=weaviate
# Prefix used to create collection name in vector database
VECTOR_INDEX_NAME_PREFIX=Vector_index

# The Weaviate endpoint URL. Only available when VECTOR_STORE is `weaviate`.
WEAVIATE_ENDPOINT=http://weaviate:8080
WEAVIATE_API_KEY=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih

# The Qdrant endpoint URL. Only available when VECTOR_STORE is `qdrant`.
QDRANT_URL=http://qdrant:6333
QDRANT_API_KEY=difyai123456
QDRANT_CLIENT_TIMEOUT=20
QDRANT_GRPC_ENABLED=false
QDRANT_GRPC_PORT=6334
QDRANT_REPLICATION_FACTOR=1

# Milvus configuration. Only available when VECTOR_STORE is `milvus`.
# The milvus uri.
MILVUS_URI=http://host.docker.internal:19530
MILVUS_DATABASE=
MILVUS_TOKEN=
MILVUS_USER=
MILVUS_PASSWORD=
MILVUS_ENABLE_HYBRID_SEARCH=False
MILVUS_ANALYZER_PARAMS=

# MyScale configuration, only available when VECTOR_STORE is `myscale`
# For multi-language support, please set MYSCALE_FTS_PARAMS with referring to:
# https://myscale.com/docs/en/text-search/#understanding-fts-index-parameters
MYSCALE_HOST=myscale
MYSCALE_PORT=8123
MYSCALE_USER=default
MYSCALE_PASSWORD=
MYSCALE_DATABASE=dify
MYSCALE_FTS_PARAMS=

# Couchbase configurations, only available when VECTOR_STORE is `couchbase`
# The connection string must include hostname defined in the docker-compose file (couchbase-server in this case)
COUCHBASE_CONNECTION_STRING=couchbase://couchbase-server
COUCHBASE_USER=Administrator
COUCHBASE_PASSWORD=password
COUCHBASE_BUCKET_NAME=Embeddings
COUCHBASE_SCOPE_NAME=_default

# pgvector configurations, only available when VECTOR_STORE is `pgvector`
PGVECTOR_HOST=pgvector
PGVECTOR_PORT=5432
PGVECTOR_USER=postgres
PGVECTOR_PASSWORD=difyai123456
PGVECTOR_DATABASE=dify
PGVECTOR_MIN_CONNECTION=1
PGVECTOR_MAX_CONNECTION=5
PGVECTOR_PG_BIGM=false
PGVECTOR_PG_BIGM_VERSION=1.2-20240606

# vastbase configurations, only available when VECTOR_STORE is `vastbase`
VASTBASE_HOST=vastbase
VASTBASE_PORT=5432
VASTBASE_USER=dify
VASTBASE_PASSWORD=Difyai123456
VASTBASE_DATABASE=dify
VASTBASE_MIN_CONNECTION=1
VASTBASE_MAX_CONNECTION=5

# pgvecto-rs configurations, only available when VECTOR_STORE is `pgvecto-rs`
PGVECTO_RS_HOST=pgvecto-rs
PGVECTO_RS_PORT=5432
PGVECTO_RS_USER=postgres
PGVECTO_RS_PASSWORD=difyai123456
PGVECTO_RS_DATABASE=dify

# analyticdb configurations, only available when VECTOR_STORE is `analyticdb`
ANALYTICDB_KEY_ID=your-ak
ANALYTICDB_KEY_SECRET=your-sk
ANALYTICDB_REGION_ID=cn-hangzhou
ANALYTICDB_INSTANCE_ID=gp-ab123456
ANALYTICDB_ACCOUNT=testaccount
ANALYTICDB_PASSWORD=testpassword
ANALYTICDB_NAMESPACE=dify
ANALYTICDB_NAMESPACE_PASSWORD=difypassword
ANALYTICDB_HOST=gp-test.aliyuncs.com
ANALYTICDB_PORT=5432
ANALYTICDB_MIN_CONNECTION=1
ANALYTICDB_MAX_CONNECTION=5

# TiDB vector configurations, only available when VECTOR_STORE is `tidb_vector`
TIDB_VECTOR_HOST=tidb
TIDB_VECTOR_PORT=4000
TIDB_VECTOR_USER=
TIDB_VECTOR_PASSWORD=
TIDB_VECTOR_DATABASE=dify

# Matrixone vector configurations.
MATRIXONE_HOST=matrixone
MATRIXONE_PORT=6001
MATRIXONE_USER=dump
MATRIXONE_PASSWORD=111
MATRIXONE_DATABASE=dify

# Tidb on qdrant configuration, only available when VECTOR_STORE is `tidb_on_qdrant`
TIDB_ON_QDRANT_URL=http://127.0.0.1
TIDB_ON_QDRANT_API_KEY=dify
TIDB_ON_QDRANT_CLIENT_TIMEOUT=20
TIDB_ON_QDRANT_GRPC_ENABLED=false
TIDB_ON_QDRANT_GRPC_PORT=6334
TIDB_PUBLIC_KEY=dify
TIDB_PRIVATE_KEY=dify
TIDB_API_URL=http://127.0.0.1
TIDB_IAM_API_URL=http://127.0.0.1
TIDB_REGION=regions/aws-us-east-1
TIDB_PROJECT_ID=dify
TIDB_SPEND_LIMIT=100

# Chroma configuration, only available when VECTOR_STORE is `chroma`
CHROMA_HOST=127.0.0.1
CHROMA_PORT=8000
CHROMA_TENANT=default_tenant
CHROMA_DATABASE=default_database
CHROMA_AUTH_PROVIDER=chromadb.auth.token_authn.TokenAuthClientProvider
CHROMA_AUTH_CREDENTIALS=

# Oracle configuration, only available when VECTOR_STORE is `oracle`
ORACLE_USER=dify
ORACLE_PASSWORD=dify
ORACLE_DSN=oracle:1521/FREEPDB1
ORACLE_CONFIG_DIR=/app/api/storage/wallet
ORACLE_WALLET_LOCATION=/app/api/storage/wallet
ORACLE_WALLET_PASSWORD=dify
ORACLE_IS_AUTONOMOUS=false

# relyt configurations, only available when VECTOR_STORE is `relyt`
RELYT_HOST=db
RELYT_PORT=5432
RELYT_USER=postgres
RELYT_PASSWORD=difyai123456
RELYT_DATABASE=postgres

# open search configuration, only available when VECTOR_STORE is `opensearch`
OPENSEARCH_HOST=opensearch
OPENSEARCH_PORT=9200
OPENSEARCH_SECURE=true
OPENSEARCH_VERIFY_CERTS=true
OPENSEARCH_AUTH_METHOD=basic
OPENSEARCH_USER=admin
OPENSEARCH_PASSWORD=admin
# If using AWS managed IAM, e.g. Managed Cluster or OpenSearch Serverless
OPENSEARCH_AWS_REGION=ap-southeast-1
OPENSEARCH_AWS_SERVICE=aoss

# tencent vector configurations, only available when VECTOR_STORE is `tencent`
TENCENT_VECTOR_DB_URL=http://127.0.0.1
TENCENT_VECTOR_DB_API_KEY=dify
TENCENT_VECTOR_DB_TIMEOUT=30
TENCENT_VECTOR_DB_USERNAME=dify
TENCENT_VECTOR_DB_DATABASE=dify
TENCENT_VECTOR_DB_SHARD=1
TENCENT_VECTOR_DB_REPLICAS=2
TENCENT_VECTOR_DB_ENABLE_HYBRID_SEARCH=false

# ElasticSearch configuration, only available when VECTOR_STORE is `elasticsearch`
ELASTICSEARCH_HOST=0.0.0.0
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=elastic
KIBANA_PORT=5601

# Using ElasticSearch Cloud Serverless, or not.
ELASTICSEARCH_USE_CLOUD=false
ELASTICSEARCH_CLOUD_URL=YOUR-ELASTICSEARCH_CLOUD_URL
ELASTICSEARCH_API_KEY=YOUR-ELASTICSEARCH_API_KEY

ELASTICSEARCH_VERIFY_CERTS=False
ELASTICSEARCH_CA_CERTS=
ELASTICSEARCH_REQUEST_TIMEOUT=100000
ELASTICSEARCH_RETRY_ON_TIMEOUT=True
ELASTICSEARCH_MAX_RETRIES=10

# baidu vector configurations, only available when VECTOR_STORE is `baidu`
BAIDU_VECTOR_DB_ENDPOINT=http://127.0.0.1:5287
BAIDU_VECTOR_DB_CONNECTION_TIMEOUT_MS=30000
BAIDU_VECTOR_DB_ACCOUNT=root
BAIDU_VECTOR_DB_API_KEY=dify
BAIDU_VECTOR_DB_DATABASE=dify
BAIDU_VECTOR_DB_SHARD=1
BAIDU_VECTOR_DB_REPLICAS=3

# VikingDB configurations, only available when VECTOR_STORE is `vikingdb`
VIKINGDB_ACCESS_KEY=your-ak
VIKINGDB_SECRET_KEY=your-sk
VIKINGDB_REGION=cn-shanghai
VIKINGDB_HOST=api-vikingdb.xxx.volces.com
VIKINGDB_SCHEMA=http
VIKINGDB_CONNECTION_TIMEOUT=30
VIKINGDB_SOCKET_TIMEOUT=30

# Lindorm configuration, only available when VECTOR_STORE is `lindorm`
LINDORM_URL=http://lindorm:30070
LINDORM_USERNAME=lindorm
LINDORM_PASSWORD=lindorm
LINDORM_QUERY_TIMEOUT=1

# OceanBase Vector configuration, only available when VECTOR_STORE is `oceanbase`
OCEANBASE_VECTOR_HOST=oceanbase
OCEANBASE_VECTOR_PORT=2881
OCEANBASE_VECTOR_USER=root@test
OCEANBASE_VECTOR_PASSWORD=difyai123456
OCEANBASE_VECTOR_DATABASE=test
OCEANBASE_CLUSTER_NAME=difyai
OCEANBASE_MEMORY_LIMIT=6G
OCEANBASE_ENABLE_HYBRID_SEARCH=false

# opengauss configurations, only available when VECTOR_STORE is `opengauss`
OPENGAUSS_HOST=opengauss
OPENGAUSS_PORT=6600
OPENGAUSS_USER=postgres
OPENGAUSS_PASSWORD=Dify@123
OPENGAUSS_DATABASE=dify
OPENGAUSS_MIN_CONNECTION=1
OPENGAUSS_MAX_CONNECTION=5
OPENGAUSS_ENABLE_PQ=false

# huawei cloud search service vector configurations, only available when VECTOR_STORE is `huawei_cloud`
HUAWEI_CLOUD_HOSTS=https://127.0.0.1:9200
HUAWEI_CLOUD_USER=admin
HUAWEI_CLOUD_PASSWORD=admin

# Upstash Vector configuration, only available when VECTOR_STORE is `upstash`
UPSTASH_VECTOR_URL=https://xxx-vector.upstash.io
UPSTASH_VECTOR_TOKEN=dify

# TableStore Vector configuration
# (only used when VECTOR_STORE is tablestore)
TABLESTORE_ENDPOINT=https://instance-name.cn-hangzhou.ots.aliyuncs.com
TABLESTORE_INSTANCE_NAME=instance-name
TABLESTORE_ACCESS_KEY_ID=xxx
TABLESTORE_ACCESS_KEY_SECRET=xxx
TABLESTORE_NORMALIZE_FULLTEXT_BM25_SCORE=false

# Clickzetta configuration, only available when VECTOR_STORE is `clickzetta`
CLICKZETTA_USERNAME=
CLICKZETTA_PASSWORD=
CLICKZETTA_INSTANCE=
CLICKZETTA_SERVICE=api.clickzetta.com
CLICKZETTA_WORKSPACE=quick_start
CLICKZETTA_VCLUSTER=default_ap
CLICKZETTA_SCHEMA=dify
CLICKZETTA_BATCH_SIZE=100
CLICKZETTA_ENABLE_INVERTED_INDEX=true
CLICKZETTA_ANALYZER_TYPE=chinese
CLICKZETTA_ANALYZER_MODE=smart
CLICKZETTA_VECTOR_DISTANCE_FUNCTION=cosine_distance

# ------------------------------
# Knowledge Configuration
# ------------------------------

# Upload file size limit, default 15M.
UPLOAD_FILE_SIZE_LIMIT=15

# The maximum number of files that can be uploaded at a time, default 5.
UPLOAD_FILE_BATCH_LIMIT=5

# ETL type, support: `dify`, `Unstructured`
# `dify` Dify's proprietary file extraction scheme
# `Unstructured` Unstructured.io file extraction scheme
ETL_TYPE=dify

# Unstructured API path and API key, needs to be configured when ETL_TYPE is Unstructured
# Or using Unstructured for document extractor node for pptx.
# For example: http://unstructured:8000/general/v0/general
UNSTRUCTURED_API_URL=
UNSTRUCTURED_API_KEY=
SCARF_NO_ANALYTICS=true

# ------------------------------
# Model Configuration
# ------------------------------

# The maximum number of tokens allowed for prompt generation.
# This setting controls the upper limit of tokens that can be used by the LLM
# when generating a prompt in the prompt generation tool.
# Default: 512 tokens.
PROMPT_GENERATION_MAX_TOKENS=512

# The maximum number of tokens allowed for code generation.
# This setting controls the upper limit of tokens that can be used by the LLM
# when generating code in the code generation tool.
# Default: 1024 tokens.
CODE_GENERATION_MAX_TOKENS=1024

# Enable or disable plugin based token counting. If disabled, token counting will return 0.
# This can improve performance by skipping token counting operations.
# Default: false (disabled).
PLUGIN_BASED_TOKEN_COUNTING_ENABLED=false

# ------------------------------
# Multi-modal Configuration
# ------------------------------

# The format of the image/video/audio/document sent when the multi-modal model is input,
# the default is base64, optional url.
# The delay of the call in url mode will be lower than that in base64 mode.
# It is generally recommended to use the more compatible base64 mode.
# If configured as url, you need to configure FILES_URL as an externally accessible address so that the multi-modal model can access the image/video/audio/document.
MULTIMODAL_SEND_FORMAT=base64
# Upload image file size limit, default 10M.
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
# Upload video file size limit, default 100M.
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
# Upload audio file size limit, default 50M.
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50

# ------------------------------
# Sentry Configuration
# Used for application monitoring and error log tracking.
# ------------------------------
SENTRY_DSN=

# API Service Sentry DSN address, default is empty, when empty,
# all monitoring information is not reported to Sentry.
# If not set, Sentry error reporting will be disabled.
API_SENTRY_DSN=
# API Service The reporting ratio of Sentry events, if it is 0.01, it is 1%.
API_SENTRY_TRACES_SAMPLE_RATE=1.0
# API Service The reporting ratio of Sentry profiles, if it is 0.01, it is 1%.
API_SENTRY_PROFILES_SAMPLE_RATE=1.0

# Web Service Sentry DSN address, default is empty, when empty,
# all monitoring information is not reported to Sentry.
# If not set, Sentry error reporting will be disabled.
WEB_SENTRY_DSN=

# ------------------------------
# Notion Integration Configuration
# Variables can be obtained by applying for Notion integration: https://www.notion.so/my-integrations
# ------------------------------

# Configure as "public" or "internal".
# Since Notion's OAuth redirect URL only supports HTTPS,
# if deploying locally, please use Notion's internal integration.
NOTION_INTEGRATION_TYPE=public
# Notion OAuth client secret (used for public integration type)
NOTION_CLIENT_SECRET=
# Notion OAuth client id (used for public integration type)
NOTION_CLIENT_ID=
# Notion internal integration secret.
# If the value of NOTION_INTEGRATION_TYPE is "internal",
# you need to configure this variable.
NOTION_INTERNAL_SECRET=

# ------------------------------
# Mail related configuration
# ------------------------------

# Mail type, support: resend, smtp, sendgrid
MAIL_TYPE=resend

# Default send from email address, if not specified
# If using SendGrid, use the 'from' field for authentication if necessary.
MAIL_DEFAULT_SEND_FROM=

# API-Key for the Resend email provider, used when MAIL_TYPE is `resend`.
RESEND_API_URL=https://api.resend.com
RESEND_API_KEY=your-resend-api-key


# SMTP server configuration, used when MAIL_TYPE is `smtp`
SMTP_SERVER=
SMTP_PORT=465
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_USE_TLS=true
SMTP_OPPORTUNISTIC_TLS=false

# Sendgid configuration
SENDGRID_API_KEY=

# ------------------------------
# Others Configuration
# ------------------------------

# Maximum length of segmentation tokens for indexing
INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=4000

# Member invitation link valid time (hours),
# Default: 72.
INVITE_EXPIRY_HOURS=72

# Reset password token valid time (minutes),
RESET_PASSWORD_TOKEN_EXPIRY_MINUTES=5
CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES=5
OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES=5

# The sandbox service endpoint.
CODE_EXECUTION_ENDPOINT=http://sandbox:8194
CODE_EXECUTION_API_KEY=dify-sandbox
CODE_MAX_NUMBER=9223372036854775807
CODE_MIN_NUMBER=-9223372036854775808
CODE_MAX_DEPTH=5
CODE_MAX_PRECISION=20
CODE_MAX_STRING_LENGTH=80000
CODE_MAX_STRING_ARRAY_LENGTH=30
CODE_MAX_OBJECT_ARRAY_LENGTH=30
CODE_MAX_NUMBER_ARRAY_LENGTH=1000
CODE_EXECUTION_CONNECT_TIMEOUT=10
CODE_EXECUTION_READ_TIMEOUT=60
CODE_EXECUTION_WRITE_TIMEOUT=10
TEMPLATE_TRANSFORM_MAX_LENGTH=80000

# Workflow runtime configuration
WORKFLOW_MAX_EXECUTION_STEPS=500
WORKFLOW_MAX_EXECUTION_TIME=1200
WORKFLOW_CALL_MAX_DEPTH=5
MAX_VARIABLE_SIZE=204800
WORKFLOW_PARALLEL_DEPTH_LIMIT=3
WORKFLOW_FILE_UPLOAD_LIMIT=10

# Workflow storage configuration
# Options: rdbms, hybrid
# rdbms: Use only the relational database (default)
# hybrid: Save new data to object storage, read from both object storage and RDBMS
WORKFLOW_NODE_EXECUTION_STORAGE=rdbms

# Repository configuration
# Core workflow execution repository implementation
# Options:
#   - core.repositories.sqlalchemy_workflow_execution_repository.SQLAlchemyWorkflowExecutionRepository (default)
#   - core.repositories.celery_workflow_execution_repository.CeleryWorkflowExecutionRepository
CORE_WORKFLOW_EXECUTION_REPOSITORY=core.repositories.sqlalchemy_workflow_execution_repository.SQLAlchemyWorkflowExecutionRepository

# Core workflow node execution repository implementation
# Options:
#   - core.repositories.sqlalchemy_workflow_node_execution_repository.SQLAlchemyWorkflowNodeExecutionRepository (default)
#   - core.repositories.celery_workflow_node_execution_repository.CeleryWorkflowNodeExecutionRepository
CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY=core.repositories.sqlalchemy_workflow_node_execution_repository.SQLAlchemyWorkflowNodeExecutionRepository

# API workflow run repository implementation
API_WORKFLOW_RUN_REPOSITORY=repositories.sqlalchemy_api_workflow_run_repository.DifyAPISQLAlchemyWorkflowRunRepository

# API workflow node execution repository implementation
API_WORKFLOW_NODE_EXECUTION_REPOSITORY=repositories.sqlalchemy_api_workflow_node_execution_repository.DifyAPISQLAlchemyWorkflowNodeExecutionRepository

# Workflow log cleanup configuration
# Enable automatic cleanup of workflow run logs to manage database size
WORKFLOW_LOG_CLEANUP_ENABLED=false
# Number of days to retain workflow run logs (default: 30 days)
WORKFLOW_LOG_RETENTION_DAYS=30
# Batch size for workflow log cleanup operations (default: 100)
WORKFLOW_LOG_CLEANUP_BATCH_SIZE=100

# HTTP request node in workflow configuration
HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760
HTTP_REQUEST_NODE_MAX_TEXT_SIZE=1048576
HTTP_REQUEST_NODE_SSL_VERIFY=True

# Respect X-* headers to redirect clients
RESPECT_XFORWARD_HEADERS_ENABLED=false

# SSRF Proxy server HTTP URL
SSRF_PROXY_HTTP_URL=http://ssrf_proxy:3128
# SSRF Proxy server HTTPS URL
SSRF_PROXY_HTTPS_URL=http://ssrf_proxy:3128

# Maximum loop count in the workflow
LOOP_NODE_MAX_COUNT=100

# The maximum number of tools that can be used in the agent.
MAX_TOOLS_NUM=10

# Maximum number of Parallelism branches in the workflow
MAX_PARALLEL_LIMIT=10

# The maximum number of iterations for agent setting
MAX_ITERATIONS_NUM=99

# ------------------------------
# Environment Variables for web Service
# ------------------------------

# The timeout for the text generation in millisecond
TEXT_GENERATION_TIMEOUT_MS=60000

# Allow rendering unsafe URLs which have "data:" scheme.
ALLOW_UNSAFE_DATA_SCHEME=false

# Maximum number of tree depth in the workflow
MAX_TREE_DEPTH=50

# ------------------------------
# Environment Variables for db Service
# ------------------------------

# The name of the default postgres user.
POSTGRES_USER=${DB_USERNAME}
# The password for the default postgres user.
POSTGRES_PASSWORD=${DB_PASSWORD}
# The name of the default postgres database.
POSTGRES_DB=${DB_DATABASE}
# postgres data directory
PGDATA=/var/lib/postgresql/data/pgdata

# ------------------------------
# Environment Variables for sandbox Service
# ------------------------------

# The API key for the sandbox service
SANDBOX_API_KEY=dify-sandbox
# The mode in which the Gin framework runs
SANDBOX_GIN_MODE=release
# The timeout for the worker in seconds
SANDBOX_WORKER_TIMEOUT=15
# Enable network for the sandbox service
SANDBOX_ENABLE_NETWORK=true
# HTTP proxy URL for SSRF protection
SANDBOX_HTTP_PROXY=http://ssrf_proxy:3128
# HTTPS proxy URL for SSRF protection
SANDBOX_HTTPS_PROXY=http://ssrf_proxy:3128
# The port on which the sandbox service runs
SANDBOX_PORT=8194

# ------------------------------
# Environment Variables for weaviate Service
# (only used when VECTOR_STORE is weaviate)
# ------------------------------
WEAVIATE_PERSISTENCE_DATA_PATH=/var/lib/weaviate
WEAVIATE_QUERY_DEFAULTS_LIMIT=25
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true
WEAVIATE_DEFAULT_VECTORIZER_MODULE=none
WEAVIATE_CLUSTER_HOSTNAME=node1
WEAVIATE_AUTHENTICATION_APIKEY_ENABLED=true
WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
WEAVIATE_AUTHENTICATION_APIKEY_USERS=hello@dify.ai
WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED=true
WEAVIATE_AUTHORIZATION_ADMINLIST_USERS=hello@dify.ai

# ------------------------------
# Environment Variables for Chroma
# (only used when VECTOR_STORE is chroma)
# ------------------------------

# Authentication credentials for Chroma server
CHROMA_SERVER_AUTHN_CREDENTIALS=difyai123456
# Authentication provider for Chroma server
CHROMA_SERVER_AUTHN_PROVIDER=chromadb.auth.token_authn.TokenAuthenticationServerProvider
# Persistence setting for Chroma server
CHROMA_IS_PERSISTENT=TRUE

# ------------------------------
# Environment Variables for Oracle Service
# (only used when VECTOR_STORE is oracle)
# ------------------------------
ORACLE_PWD=Dify123456
ORACLE_CHARACTERSET=AL32UTF8

# ------------------------------
# Environment Variables for milvus Service
# (only used when VECTOR_STORE is milvus)
# ------------------------------
# ETCD configuration for auto compaction mode
ETCD_AUTO_COMPACTION_MODE=revision
# ETCD configuration for auto compaction retention in terms of number of revisions
ETCD_AUTO_COMPACTION_RETENTION=1000
# ETCD configuration for backend quota in bytes
ETCD_QUOTA_BACKEND_BYTES=4294967296
# ETCD configuration for the number of changes before triggering a snapshot
ETCD_SNAPSHOT_COUNT=50000
# MinIO access key for authentication
MINIO_ACCESS_KEY=minioadmin
# MinIO secret key for authentication
MINIO_SECRET_KEY=minioadmin
# ETCD service endpoints
ETCD_ENDPOINTS=etcd:2379
# MinIO service address
MINIO_ADDRESS=minio:9000
# Enable or disable security authorization
MILVUS_AUTHORIZATION_ENABLED=true

# ------------------------------
# Environment Variables for pgvector / pgvector-rs Service
# (only used when VECTOR_STORE is pgvector / pgvector-rs)
# ------------------------------
PGVECTOR_PGUSER=postgres
# The password for the default postgres user.
PGVECTOR_POSTGRES_PASSWORD=difyai123456
# The name of the default postgres database.
PGVECTOR_POSTGRES_DB=dify
# postgres data directory
PGVECTOR_PGDATA=/var/lib/postgresql/data/pgdata

# ------------------------------
# Environment Variables for opensearch
# (only used when VECTOR_STORE is opensearch)
# ------------------------------
OPENSEARCH_DISCOVERY_TYPE=single-node
OPENSEARCH_BOOTSTRAP_MEMORY_LOCK=true
OPENSEARCH_JAVA_OPTS_MIN=512m
OPENSEARCH_JAVA_OPTS_MAX=1024m
OPENSEARCH_INITIAL_ADMIN_PASSWORD=Qazwsxedc!@#123
OPENSEARCH_MEMLOCK_SOFT=-1
OPENSEARCH_MEMLOCK_HARD=-1
OPENSEARCH_NOFILE_SOFT=65536
OPENSEARCH_NOFILE_HARD=65536

# ------------------------------
# Environment Variables for Nginx reverse proxy
# ------------------------------
NGINX_SERVER_NAME=_
NGINX_HTTPS_ENABLED=false
# HTTP port
NGINX_PORT=80
# SSL settings are only applied when HTTPS_ENABLED is true
NGINX_SSL_PORT=443
# if HTTPS_ENABLED is true, you're required to add your own SSL certificates/keys to the `./nginx/ssl` directory
# and modify the env vars below accordingly.
NGINX_SSL_CERT_FILENAME=dify.crt
NGINX_SSL_CERT_KEY_FILENAME=dify.key
NGINX_SSL_PROTOCOLS=TLSv1.1 TLSv1.2 TLSv1.3

# Nginx performance tuning
NGINX_WORKER_PROCESSES=auto
NGINX_CLIENT_MAX_BODY_SIZE=100M
NGINX_KEEPALIVE_TIMEOUT=65

# Proxy settings
NGINX_PROXY_READ_TIMEOUT=3600s
NGINX_PROXY_SEND_TIMEOUT=3600s

# Set true to accept requests for /.well-known/acme-challenge/
NGINX_ENABLE_CERTBOT_CHALLENGE=false

# ------------------------------
# Certbot Configuration
# ------------------------------

# Email address (required to get certificates from Let's Encrypt)
CERTBOT_EMAIL=your_email@example.com

# Domain name
CERTBOT_DOMAIN=your_domain.com

# certbot command options
# i.e: --force-renewal --dry-run --test-cert --debug
CERTBOT_OPTIONS=

# ------------------------------
# Environment Variables for SSRF Proxy
# ------------------------------
SSRF_HTTP_PORT=3128
SSRF_COREDUMP_DIR=/var/spool/squid
SSRF_REVERSE_PROXY_PORT=8194
SSRF_SANDBOX_HOST=sandbox
SSRF_DEFAULT_TIME_OUT=5
SSRF_DEFAULT_CONNECT_TIME_OUT=5
SSRF_DEFAULT_READ_TIME_OUT=5
SSRF_DEFAULT_WRITE_TIME_OUT=5

# ------------------------------
# docker env var for specifying vector db type at startup
# (based on the vector db type, the corresponding docker
# compose profile will be used)
# if you want to use unstructured, add ',unstructured' to the end
# ------------------------------
COMPOSE_PROFILES=${VECTOR_STORE:-weaviate}

# ------------------------------
# Docker Compose Service Expose Host Port Configurations
# ------------------------------
EXPOSE_NGINX_PORT=80
EXPOSE_NGINX_SSL_PORT=443

# ----------------------------------------------------------------------------
# ModelProvider &amp; Tool Position Configuration
# Used to specify the model providers and tools that can be used in the app.
# ----------------------------------------------------------------------------

# Pin, include, and exclude tools
# Use comma-separated values with no spaces between items.
# Example: POSITION_TOOL_PINS=bing,google
POSITION_TOOL_PINS=
POSITION_TOOL_INCLUDES=
POSITION_TOOL_EXCLUDES=

# Pin, include, and exclude model providers
# Use comma-separated values with no spaces between items.
# Example: POSITION_PROVIDER_PINS=openai,openllm
POSITION_PROVIDER_PINS=
POSITION_PROVIDER_INCLUDES=
POSITION_PROVIDER_EXCLUDES=

# CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
CSP_WHITELIST=

# Enable or disable create tidb service job
CREATE_TIDB_SERVICE_JOB_ENABLED=false

# Maximum number of submitted thread count in a ThreadPool for parallel node execution
MAX_SUBMIT_COUNT=100

# The maximum number of top-k value for RAG.
TOP_K_MAX_VALUE=10

# ------------------------------
# Plugin Daemon Configuration
# ------------------------------

DB_PLUGIN_DATABASE=dify_plugin
EXPOSE_PLUGIN_DAEMON_PORT=5002
PLUGIN_DAEMON_PORT=5002
PLUGIN_DAEMON_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
PLUGIN_DAEMON_URL=http://plugin_daemon:5002
PLUGIN_MAX_PACKAGE_SIZE=52428800
PLUGIN_PPROF_ENABLED=false

PLUGIN_DEBUGGING_HOST=0.0.0.0
PLUGIN_DEBUGGING_PORT=5003
EXPOSE_PLUGIN_DEBUGGING_HOST=localhost
EXPOSE_PLUGIN_DEBUGGING_PORT=5003

# If this key is changed, DIFY_INNER_API_KEY in plugin_daemon service must also be updated or agent node will fail.
PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
PLUGIN_DIFY_INNER_API_URL=http://api:5001

ENDPOINT_URL_TEMPLATE=http://localhost/e/{hook_id}

MARKETPLACE_ENABLED=true
MARKETPLACE_API_URL=https://marketplace.dify.ai

FORCE_VERIFYING_SIGNATURE=true

PLUGIN_STDIO_BUFFER_SIZE=1024
PLUGIN_STDIO_MAX_BUFFER_SIZE=5242880

PLUGIN_PYTHON_ENV_INIT_TIMEOUT=120
PLUGIN_MAX_EXECUTION_TIMEOUT=600
# PIP_MIRROR_URL=https://pypi.tuna.tsinghua.edu.cn/simple
PIP_MIRROR_URL=

# https://github.com/langgenius/dify-plugin-daemon/blob/main/.env.example
# Plugin storage type, local aws_s3 tencent_cos azure_blob aliyun_oss volcengine_tos
PLUGIN_STORAGE_TYPE=local
PLUGIN_STORAGE_LOCAL_ROOT=/app/storage
PLUGIN_WORKING_PATH=/app/storage/cwd
PLUGIN_INSTALLED_PATH=plugin
PLUGIN_PACKAGE_CACHE_PATH=plugin_packages
PLUGIN_MEDIA_CACHE_PATH=assets
# Plugin oss bucket
PLUGIN_STORAGE_OSS_BUCKET=
# Plugin oss s3 credentials
PLUGIN_S3_USE_AWS=false
PLUGIN_S3_USE_AWS_MANAGED_IAM=false
PLUGIN_S3_ENDPOINT=
PLUGIN_S3_USE_PATH_STYLE=false
PLUGIN_AWS_ACCESS_KEY=
PLUGIN_AWS_SECRET_KEY=
PLUGIN_AWS_REGION=
# Plugin oss azure blob
PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME=
PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING=
# Plugin oss tencent cos
PLUGIN_TENCENT_COS_SECRET_KEY=
PLUGIN_TENCENT_COS_SECRET_ID=
PLUGIN_TENCENT_COS_REGION=
# Plugin oss aliyun oss
PLUGIN_ALIYUN_OSS_REGION=
PLUGIN_ALIYUN_OSS_ENDPOINT=
PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID=
PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET=
PLUGIN_ALIYUN_OSS_AUTH_VERSION=v4
PLUGIN_ALIYUN_OSS_PATH=
# Plugin oss volcengine tos
PLUGIN_VOLCENGINE_TOS_ENDPOINT=
PLUGIN_VOLCENGINE_TOS_ACCESS_KEY=
PLUGIN_VOLCENGINE_TOS_SECRET_KEY=
PLUGIN_VOLCENGINE_TOS_REGION=

# ------------------------------
# OTLP Collector Configuration
# ------------------------------
ENABLE_OTEL=false
OTLP_TRACE_ENDPOINT=
OTLP_METRIC_ENDPOINT=
OTLP_BASE_ENDPOINT=http://localhost:4318
OTLP_API_KEY=
OTEL_EXPORTER_OTLP_PROTOCOL=
OTEL_EXPORTER_TYPE=otlp
OTEL_SAMPLING_RATE=0.1
OTEL_BATCH_EXPORT_SCHEDULE_DELAY=5000
OTEL_MAX_QUEUE_SIZE=2048
OTEL_MAX_EXPORT_BATCH_SIZE=512
OTEL_METRIC_EXPORT_INTERVAL=60000
OTEL_BATCH_EXPORT_TIMEOUT=10000
OTEL_METRIC_EXPORT_TIMEOUT=30000

# Prevent Clickjacking
ALLOW_EMBED=false

# Dataset queue monitor configuration
QUEUE_MONITOR_THRESHOLD=200
# You can configure multiple ones, separated by commas. eg: test1@dify.ai,test2@dify.ai
QUEUE_MONITOR_ALERT_EMAILS=
# Monitor interval in minutes, default is 30 minutes
QUEUE_MONITOR_INTERVAL=30

# Swagger UI configuration
SWAGGER_UI_ENABLED=true
SWAGGER_UI_PATH=/swagger-ui.html

# Celery schedule tasks configuration
ENABLE_CLEAN_EMBEDDING_CACHE_TASK=false
ENABLE_CLEAN_UNUSED_DATASETS_TASK=false
ENABLE_CREATE_TIDB_SERVERLESS_TASK=false
ENABLE_UPDATE_TIDB_SERVERLESS_STATUS_TASK=false
ENABLE_CLEAN_MESSAGES=false
ENABLE_MAIL_CLEAN_DOCUMENT_NOTIFY_TASK=false
ENABLE_DATASETS_QUEUE_MONITOR=false
ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK=true
</code></pre>
<p>太长了，其实很多都可以安装好之后，我们慢慢配置的，这边先无视它……</p>
<p>然后处于好奇，我们来看一下它的<code>docker-compose.yml</code>文件</p>
<pre><code class="language-yaml"># ==================================================================
# WARNING: This file is auto-generated by generate_docker_compose
# Do not modify this file directly. Instead, update the .env.example
# or docker-compose-template.yaml and regenerate this file.
# ==================================================================

x-shared-env: &amp;shared-api-worker-env
  CONSOLE_API_URL: ${CONSOLE_API_URL:-}
  CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-}
  SERVICE_API_URL: ${SERVICE_API_URL:-}
  APP_API_URL: ${APP_API_URL:-}
  APP_WEB_URL: ${APP_WEB_URL:-}
  FILES_URL: ${FILES_URL:-}
  INTERNAL_FILES_URL: ${INTERNAL_FILES_URL:-}
  LANG: ${LANG:-en_US.UTF-8}
  LC_ALL: ${LC_ALL:-en_US.UTF-8}
  PYTHONIOENCODING: ${PYTHONIOENCODING:-utf-8}
  LOG_LEVEL: ${LOG_LEVEL:-INFO}
  LOG_FILE: ${LOG_FILE:-/app/logs/server.log}
  LOG_FILE_MAX_SIZE: ${LOG_FILE_MAX_SIZE:-20}
  LOG_FILE_BACKUP_COUNT: ${LOG_FILE_BACKUP_COUNT:-5}
  LOG_DATEFORMAT: ${LOG_DATEFORMAT:-%Y-%m-%d %H:%M:%S}
  LOG_TZ: ${LOG_TZ:-UTC}
  DEBUG: ${DEBUG:-false}
  FLASK_DEBUG: ${FLASK_DEBUG:-false}
  ENABLE_REQUEST_LOGGING: ${ENABLE_REQUEST_LOGGING:-False}
  SECRET_KEY: ${SECRET_KEY:-sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U}
  INIT_PASSWORD: ${INIT_PASSWORD:-}
  DEPLOY_ENV: ${DEPLOY_ENV:-PRODUCTION}
  CHECK_UPDATE_URL: ${CHECK_UPDATE_URL:-https://updates.dify.ai}
  OPENAI_API_BASE: ${OPENAI_API_BASE:-https://api.openai.com/v1}
  MIGRATION_ENABLED: ${MIGRATION_ENABLED:-true}
  FILES_ACCESS_TIMEOUT: ${FILES_ACCESS_TIMEOUT:-300}
  ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-60}
  REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS:-30}
  APP_MAX_ACTIVE_REQUESTS: ${APP_MAX_ACTIVE_REQUESTS:-0}
  APP_MAX_EXECUTION_TIME: ${APP_MAX_EXECUTION_TIME:-1200}
  DIFY_BIND_ADDRESS: ${DIFY_BIND_ADDRESS:-0.0.0.0}
  DIFY_PORT: ${DIFY_PORT:-5001}
  SERVER_WORKER_AMOUNT: ${SERVER_WORKER_AMOUNT:-1}
  SERVER_WORKER_CLASS: ${SERVER_WORKER_CLASS:-gevent}
  SERVER_WORKER_CONNECTIONS: ${SERVER_WORKER_CONNECTIONS:-10}
  CELERY_WORKER_CLASS: ${CELERY_WORKER_CLASS:-}
  GUNICORN_TIMEOUT: ${GUNICORN_TIMEOUT:-360}
  CELERY_WORKER_AMOUNT: ${CELERY_WORKER_AMOUNT:-}
  CELERY_AUTO_SCALE: ${CELERY_AUTO_SCALE:-false}
  CELERY_MAX_WORKERS: ${CELERY_MAX_WORKERS:-}
  CELERY_MIN_WORKERS: ${CELERY_MIN_WORKERS:-}
  API_TOOL_DEFAULT_CONNECT_TIMEOUT: ${API_TOOL_DEFAULT_CONNECT_TIMEOUT:-10}
  API_TOOL_DEFAULT_READ_TIMEOUT: ${API_TOOL_DEFAULT_READ_TIMEOUT:-60}
  ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
  ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
  ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}
  DB_USERNAME: ${DB_USERNAME:-postgres}
  DB_PASSWORD: ${DB_PASSWORD:-difyai123456}
  DB_HOST: ${DB_HOST:-db}
  DB_PORT: ${DB_PORT:-5432}
  DB_DATABASE: ${DB_DATABASE:-dify}
  SQLALCHEMY_POOL_SIZE: ${SQLALCHEMY_POOL_SIZE:-30}
  SQLALCHEMY_MAX_OVERFLOW: ${SQLALCHEMY_MAX_OVERFLOW:-10}
  SQLALCHEMY_POOL_RECYCLE: ${SQLALCHEMY_POOL_RECYCLE:-3600}
  SQLALCHEMY_ECHO: ${SQLALCHEMY_ECHO:-false}
  SQLALCHEMY_POOL_PRE_PING: ${SQLALCHEMY_POOL_PRE_PING:-false}
  SQLALCHEMY_POOL_USE_LIFO: ${SQLALCHEMY_POOL_USE_LIFO:-false}
  POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100}
  POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-128MB}
  POSTGRES_WORK_MEM: ${POSTGRES_WORK_MEM:-4MB}
  POSTGRES_MAINTENANCE_WORK_MEM: ${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}
  POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}
  REDIS_HOST: ${REDIS_HOST:-redis}
  REDIS_PORT: ${REDIS_PORT:-6379}
  REDIS_USERNAME: ${REDIS_USERNAME:-}
  REDIS_PASSWORD: ${REDIS_PASSWORD:-difyai123456}
  REDIS_USE_SSL: ${REDIS_USE_SSL:-false}
  REDIS_SSL_CERT_REQS: ${REDIS_SSL_CERT_REQS:-CERT_NONE}
  REDIS_SSL_CA_CERTS: ${REDIS_SSL_CA_CERTS:-}
  REDIS_SSL_CERTFILE: ${REDIS_SSL_CERTFILE:-}
  REDIS_SSL_KEYFILE: ${REDIS_SSL_KEYFILE:-}
  REDIS_DB: ${REDIS_DB:-0}
  REDIS_USE_SENTINEL: ${REDIS_USE_SENTINEL:-false}
  REDIS_SENTINELS: ${REDIS_SENTINELS:-}
  REDIS_SENTINEL_SERVICE_NAME: ${REDIS_SENTINEL_SERVICE_NAME:-}
  REDIS_SENTINEL_USERNAME: ${REDIS_SENTINEL_USERNAME:-}
  REDIS_SENTINEL_PASSWORD: ${REDIS_SENTINEL_PASSWORD:-}
  REDIS_SENTINEL_SOCKET_TIMEOUT: ${REDIS_SENTINEL_SOCKET_TIMEOUT:-0.1}
  REDIS_USE_CLUSTERS: ${REDIS_USE_CLUSTERS:-false}
  REDIS_CLUSTERS: ${REDIS_CLUSTERS:-}
  REDIS_CLUSTERS_PASSWORD: ${REDIS_CLUSTERS_PASSWORD:-}
  CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://:difyai123456@redis:6379/1}
  CELERY_BACKEND: ${CELERY_BACKEND:-redis}
  BROKER_USE_SSL: ${BROKER_USE_SSL:-false}
  CELERY_USE_SENTINEL: ${CELERY_USE_SENTINEL:-false}
  CELERY_SENTINEL_MASTER_NAME: ${CELERY_SENTINEL_MASTER_NAME:-}
  CELERY_SENTINEL_PASSWORD: ${CELERY_SENTINEL_PASSWORD:-}
  CELERY_SENTINEL_SOCKET_TIMEOUT: ${CELERY_SENTINEL_SOCKET_TIMEOUT:-0.1}
  WEB_API_CORS_ALLOW_ORIGINS: ${WEB_API_CORS_ALLOW_ORIGINS:-*}
  CONSOLE_CORS_ALLOW_ORIGINS: ${CONSOLE_CORS_ALLOW_ORIGINS:-*}
  STORAGE_TYPE: ${STORAGE_TYPE:-opendal}
  OPENDAL_SCHEME: ${OPENDAL_SCHEME:-fs}
  OPENDAL_FS_ROOT: ${OPENDAL_FS_ROOT:-storage}
  CLICKZETTA_VOLUME_TYPE: ${CLICKZETTA_VOLUME_TYPE:-user}
  CLICKZETTA_VOLUME_NAME: ${CLICKZETTA_VOLUME_NAME:-}
  CLICKZETTA_VOLUME_TABLE_PREFIX: ${CLICKZETTA_VOLUME_TABLE_PREFIX:-dataset_}
  CLICKZETTA_VOLUME_DIFY_PREFIX: ${CLICKZETTA_VOLUME_DIFY_PREFIX:-dify_km}
  S3_ENDPOINT: ${S3_ENDPOINT:-}
  S3_REGION: ${S3_REGION:-us-east-1}
  S3_BUCKET_NAME: ${S3_BUCKET_NAME:-difyai}
  S3_ACCESS_KEY: ${S3_ACCESS_KEY:-}
  S3_SECRET_KEY: ${S3_SECRET_KEY:-}
  S3_USE_AWS_MANAGED_IAM: ${S3_USE_AWS_MANAGED_IAM:-false}
  AZURE_BLOB_ACCOUNT_NAME: ${AZURE_BLOB_ACCOUNT_NAME:-difyai}
  AZURE_BLOB_ACCOUNT_KEY: ${AZURE_BLOB_ACCOUNT_KEY:-difyai}
  AZURE_BLOB_CONTAINER_NAME: ${AZURE_BLOB_CONTAINER_NAME:-difyai-container}
  AZURE_BLOB_ACCOUNT_URL: ${AZURE_BLOB_ACCOUNT_URL:-https://&lt;your_account_name&gt;.blob.core.windows.net}
  GOOGLE_STORAGE_BUCKET_NAME: ${GOOGLE_STORAGE_BUCKET_NAME:-your-bucket-name}
  GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64: ${GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64:-}
  ALIYUN_OSS_BUCKET_NAME: ${ALIYUN_OSS_BUCKET_NAME:-your-bucket-name}
  ALIYUN_OSS_ACCESS_KEY: ${ALIYUN_OSS_ACCESS_KEY:-your-access-key}
  ALIYUN_OSS_SECRET_KEY: ${ALIYUN_OSS_SECRET_KEY:-your-secret-key}
  ALIYUN_OSS_ENDPOINT: ${ALIYUN_OSS_ENDPOINT:-https://oss-ap-southeast-1-internal.aliyuncs.com}
  ALIYUN_OSS_REGION: ${ALIYUN_OSS_REGION:-ap-southeast-1}
  ALIYUN_OSS_AUTH_VERSION: ${ALIYUN_OSS_AUTH_VERSION:-v4}
  ALIYUN_OSS_PATH: ${ALIYUN_OSS_PATH:-your-path}
  TENCENT_COS_BUCKET_NAME: ${TENCENT_COS_BUCKET_NAME:-your-bucket-name}
  TENCENT_COS_SECRET_KEY: ${TENCENT_COS_SECRET_KEY:-your-secret-key}
  TENCENT_COS_SECRET_ID: ${TENCENT_COS_SECRET_ID:-your-secret-id}
  TENCENT_COS_REGION: ${TENCENT_COS_REGION:-your-region}
  TENCENT_COS_SCHEME: ${TENCENT_COS_SCHEME:-your-scheme}
  OCI_ENDPOINT: ${OCI_ENDPOINT:-https://your-object-storage-namespace.compat.objectstorage.us-ashburn-1.oraclecloud.com}
  OCI_BUCKET_NAME: ${OCI_BUCKET_NAME:-your-bucket-name}
  OCI_ACCESS_KEY: ${OCI_ACCESS_KEY:-your-access-key}
  OCI_SECRET_KEY: ${OCI_SECRET_KEY:-your-secret-key}
  OCI_REGION: ${OCI_REGION:-us-ashburn-1}
  HUAWEI_OBS_BUCKET_NAME: ${HUAWEI_OBS_BUCKET_NAME:-your-bucket-name}
  HUAWEI_OBS_SECRET_KEY: ${HUAWEI_OBS_SECRET_KEY:-your-secret-key}
  HUAWEI_OBS_ACCESS_KEY: ${HUAWEI_OBS_ACCESS_KEY:-your-access-key}
  HUAWEI_OBS_SERVER: ${HUAWEI_OBS_SERVER:-your-server-url}
  VOLCENGINE_TOS_BUCKET_NAME: ${VOLCENGINE_TOS_BUCKET_NAME:-your-bucket-name}
  VOLCENGINE_TOS_SECRET_KEY: ${VOLCENGINE_TOS_SECRET_KEY:-your-secret-key}
  VOLCENGINE_TOS_ACCESS_KEY: ${VOLCENGINE_TOS_ACCESS_KEY:-your-access-key}
  VOLCENGINE_TOS_ENDPOINT: ${VOLCENGINE_TOS_ENDPOINT:-your-server-url}
  VOLCENGINE_TOS_REGION: ${VOLCENGINE_TOS_REGION:-your-region}
  BAIDU_OBS_BUCKET_NAME: ${BAIDU_OBS_BUCKET_NAME:-your-bucket-name}
  BAIDU_OBS_SECRET_KEY: ${BAIDU_OBS_SECRET_KEY:-your-secret-key}
  BAIDU_OBS_ACCESS_KEY: ${BAIDU_OBS_ACCESS_KEY:-your-access-key}
  BAIDU_OBS_ENDPOINT: ${BAIDU_OBS_ENDPOINT:-your-server-url}
  SUPABASE_BUCKET_NAME: ${SUPABASE_BUCKET_NAME:-your-bucket-name}
  SUPABASE_API_KEY: ${SUPABASE_API_KEY:-your-access-key}
  SUPABASE_URL: ${SUPABASE_URL:-your-server-url}
  VECTOR_STORE: ${VECTOR_STORE:-weaviate}
  VECTOR_INDEX_NAME_PREFIX: ${VECTOR_INDEX_NAME_PREFIX:-Vector_index}
  WEAVIATE_ENDPOINT: ${WEAVIATE_ENDPOINT:-http://weaviate:8080}
  WEAVIATE_API_KEY: ${WEAVIATE_API_KEY:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih}
  QDRANT_URL: ${QDRANT_URL:-http://qdrant:6333}
  QDRANT_API_KEY: ${QDRANT_API_KEY:-difyai123456}
  QDRANT_CLIENT_TIMEOUT: ${QDRANT_CLIENT_TIMEOUT:-20}
  QDRANT_GRPC_ENABLED: ${QDRANT_GRPC_ENABLED:-false}
  QDRANT_GRPC_PORT: ${QDRANT_GRPC_PORT:-6334}
  QDRANT_REPLICATION_FACTOR: ${QDRANT_REPLICATION_FACTOR:-1}
  MILVUS_URI: ${MILVUS_URI:-http://host.docker.internal:19530}
  MILVUS_DATABASE: ${MILVUS_DATABASE:-}
  MILVUS_TOKEN: ${MILVUS_TOKEN:-}
  MILVUS_USER: ${MILVUS_USER:-}
  MILVUS_PASSWORD: ${MILVUS_PASSWORD:-}
  MILVUS_ENABLE_HYBRID_SEARCH: ${MILVUS_ENABLE_HYBRID_SEARCH:-False}
  MILVUS_ANALYZER_PARAMS: ${MILVUS_ANALYZER_PARAMS:-}
  MYSCALE_HOST: ${MYSCALE_HOST:-myscale}
  MYSCALE_PORT: ${MYSCALE_PORT:-8123}
  MYSCALE_USER: ${MYSCALE_USER:-default}
  MYSCALE_PASSWORD: ${MYSCALE_PASSWORD:-}
  MYSCALE_DATABASE: ${MYSCALE_DATABASE:-dify}
  MYSCALE_FTS_PARAMS: ${MYSCALE_FTS_PARAMS:-}
  COUCHBASE_CONNECTION_STRING: ${COUCHBASE_CONNECTION_STRING:-couchbase://couchbase-server}
  COUCHBASE_USER: ${COUCHBASE_USER:-Administrator}
  COUCHBASE_PASSWORD: ${COUCHBASE_PASSWORD:-password}
  COUCHBASE_BUCKET_NAME: ${COUCHBASE_BUCKET_NAME:-Embeddings}
  COUCHBASE_SCOPE_NAME: ${COUCHBASE_SCOPE_NAME:-_default}
  PGVECTOR_HOST: ${PGVECTOR_HOST:-pgvector}
  PGVECTOR_PORT: ${PGVECTOR_PORT:-5432}
  PGVECTOR_USER: ${PGVECTOR_USER:-postgres}
  PGVECTOR_PASSWORD: ${PGVECTOR_PASSWORD:-difyai123456}
  PGVECTOR_DATABASE: ${PGVECTOR_DATABASE:-dify}
  PGVECTOR_MIN_CONNECTION: ${PGVECTOR_MIN_CONNECTION:-1}
  PGVECTOR_MAX_CONNECTION: ${PGVECTOR_MAX_CONNECTION:-5}
  PGVECTOR_PG_BIGM: ${PGVECTOR_PG_BIGM:-false}
  PGVECTOR_PG_BIGM_VERSION: ${PGVECTOR_PG_BIGM_VERSION:-1.2-20240606}
  VASTBASE_HOST: ${VASTBASE_HOST:-vastbase}
  VASTBASE_PORT: ${VASTBASE_PORT:-5432}
  VASTBASE_USER: ${VASTBASE_USER:-dify}
  VASTBASE_PASSWORD: ${VASTBASE_PASSWORD:-Difyai123456}
  VASTBASE_DATABASE: ${VASTBASE_DATABASE:-dify}
  VASTBASE_MIN_CONNECTION: ${VASTBASE_MIN_CONNECTION:-1}
  VASTBASE_MAX_CONNECTION: ${VASTBASE_MAX_CONNECTION:-5}
  PGVECTO_RS_HOST: ${PGVECTO_RS_HOST:-pgvecto-rs}
  PGVECTO_RS_PORT: ${PGVECTO_RS_PORT:-5432}
  PGVECTO_RS_USER: ${PGVECTO_RS_USER:-postgres}
  PGVECTO_RS_PASSWORD: ${PGVECTO_RS_PASSWORD:-difyai123456}
  PGVECTO_RS_DATABASE: ${PGVECTO_RS_DATABASE:-dify}
  ANALYTICDB_KEY_ID: ${ANALYTICDB_KEY_ID:-your-ak}
  ANALYTICDB_KEY_SECRET: ${ANALYTICDB_KEY_SECRET:-your-sk}
  ANALYTICDB_REGION_ID: ${ANALYTICDB_REGION_ID:-cn-hangzhou}
  ANALYTICDB_INSTANCE_ID: ${ANALYTICDB_INSTANCE_ID:-gp-ab123456}
  ANALYTICDB_ACCOUNT: ${ANALYTICDB_ACCOUNT:-testaccount}
  ANALYTICDB_PASSWORD: ${ANALYTICDB_PASSWORD:-testpassword}
  ANALYTICDB_NAMESPACE: ${ANALYTICDB_NAMESPACE:-dify}
  ANALYTICDB_NAMESPACE_PASSWORD: ${ANALYTICDB_NAMESPACE_PASSWORD:-difypassword}
  ANALYTICDB_HOST: ${ANALYTICDB_HOST:-gp-test.aliyuncs.com}
  ANALYTICDB_PORT: ${ANALYTICDB_PORT:-5432}
  ANALYTICDB_MIN_CONNECTION: ${ANALYTICDB_MIN_CONNECTION:-1}
  ANALYTICDB_MAX_CONNECTION: ${ANALYTICDB_MAX_CONNECTION:-5}
  TIDB_VECTOR_HOST: ${TIDB_VECTOR_HOST:-tidb}
  TIDB_VECTOR_PORT: ${TIDB_VECTOR_PORT:-4000}
  TIDB_VECTOR_USER: ${TIDB_VECTOR_USER:-}
  TIDB_VECTOR_PASSWORD: ${TIDB_VECTOR_PASSWORD:-}
  TIDB_VECTOR_DATABASE: ${TIDB_VECTOR_DATABASE:-dify}
  MATRIXONE_HOST: ${MATRIXONE_HOST:-matrixone}
  MATRIXONE_PORT: ${MATRIXONE_PORT:-6001}
  MATRIXONE_USER: ${MATRIXONE_USER:-dump}
  MATRIXONE_PASSWORD: ${MATRIXONE_PASSWORD:-111}
  MATRIXONE_DATABASE: ${MATRIXONE_DATABASE:-dify}
  TIDB_ON_QDRANT_URL: ${TIDB_ON_QDRANT_URL:-http://127.0.0.1}
  TIDB_ON_QDRANT_API_KEY: ${TIDB_ON_QDRANT_API_KEY:-dify}
  TIDB_ON_QDRANT_CLIENT_TIMEOUT: ${TIDB_ON_QDRANT_CLIENT_TIMEOUT:-20}
  TIDB_ON_QDRANT_GRPC_ENABLED: ${TIDB_ON_QDRANT_GRPC_ENABLED:-false}
  TIDB_ON_QDRANT_GRPC_PORT: ${TIDB_ON_QDRANT_GRPC_PORT:-6334}
  TIDB_PUBLIC_KEY: ${TIDB_PUBLIC_KEY:-dify}
  TIDB_PRIVATE_KEY: ${TIDB_PRIVATE_KEY:-dify}
  TIDB_API_URL: ${TIDB_API_URL:-http://127.0.0.1}
  TIDB_IAM_API_URL: ${TIDB_IAM_API_URL:-http://127.0.0.1}
  TIDB_REGION: ${TIDB_REGION:-regions/aws-us-east-1}
  TIDB_PROJECT_ID: ${TIDB_PROJECT_ID:-dify}
  TIDB_SPEND_LIMIT: ${TIDB_SPEND_LIMIT:-100}
  CHROMA_HOST: ${CHROMA_HOST:-127.0.0.1}
  CHROMA_PORT: ${CHROMA_PORT:-8000}
  CHROMA_TENANT: ${CHROMA_TENANT:-default_tenant}
  CHROMA_DATABASE: ${CHROMA_DATABASE:-default_database}
  CHROMA_AUTH_PROVIDER: ${CHROMA_AUTH_PROVIDER:-chromadb.auth.token_authn.TokenAuthClientProvider}
  CHROMA_AUTH_CREDENTIALS: ${CHROMA_AUTH_CREDENTIALS:-}
  ORACLE_USER: ${ORACLE_USER:-dify}
  ORACLE_PASSWORD: ${ORACLE_PASSWORD:-dify}
  ORACLE_DSN: ${ORACLE_DSN:-oracle:1521/FREEPDB1}
  ORACLE_CONFIG_DIR: ${ORACLE_CONFIG_DIR:-/app/api/storage/wallet}
  ORACLE_WALLET_LOCATION: ${ORACLE_WALLET_LOCATION:-/app/api/storage/wallet}
  ORACLE_WALLET_PASSWORD: ${ORACLE_WALLET_PASSWORD:-dify}
  ORACLE_IS_AUTONOMOUS: ${ORACLE_IS_AUTONOMOUS:-false}
  RELYT_HOST: ${RELYT_HOST:-db}
  RELYT_PORT: ${RELYT_PORT:-5432}
  RELYT_USER: ${RELYT_USER:-postgres}
  RELYT_PASSWORD: ${RELYT_PASSWORD:-difyai123456}
  RELYT_DATABASE: ${RELYT_DATABASE:-postgres}
  OPENSEARCH_HOST: ${OPENSEARCH_HOST:-opensearch}
  OPENSEARCH_PORT: ${OPENSEARCH_PORT:-9200}
  OPENSEARCH_SECURE: ${OPENSEARCH_SECURE:-true}
  OPENSEARCH_VERIFY_CERTS: ${OPENSEARCH_VERIFY_CERTS:-true}
  OPENSEARCH_AUTH_METHOD: ${OPENSEARCH_AUTH_METHOD:-basic}
  OPENSEARCH_USER: ${OPENSEARCH_USER:-admin}
  OPENSEARCH_PASSWORD: ${OPENSEARCH_PASSWORD:-admin}
  OPENSEARCH_AWS_REGION: ${OPENSEARCH_AWS_REGION:-ap-southeast-1}
  OPENSEARCH_AWS_SERVICE: ${OPENSEARCH_AWS_SERVICE:-aoss}
  TENCENT_VECTOR_DB_URL: ${TENCENT_VECTOR_DB_URL:-http://127.0.0.1}
  TENCENT_VECTOR_DB_API_KEY: ${TENCENT_VECTOR_DB_API_KEY:-dify}
  TENCENT_VECTOR_DB_TIMEOUT: ${TENCENT_VECTOR_DB_TIMEOUT:-30}
  TENCENT_VECTOR_DB_USERNAME: ${TENCENT_VECTOR_DB_USERNAME:-dify}
  TENCENT_VECTOR_DB_DATABASE: ${TENCENT_VECTOR_DB_DATABASE:-dify}
  TENCENT_VECTOR_DB_SHARD: ${TENCENT_VECTOR_DB_SHARD:-1}
  TENCENT_VECTOR_DB_REPLICAS: ${TENCENT_VECTOR_DB_REPLICAS:-2}
  TENCENT_VECTOR_DB_ENABLE_HYBRID_SEARCH: ${TENCENT_VECTOR_DB_ENABLE_HYBRID_SEARCH:-false}
  ELASTICSEARCH_HOST: ${ELASTICSEARCH_HOST:-0.0.0.0}
  ELASTICSEARCH_PORT: ${ELASTICSEARCH_PORT:-9200}
  ELASTICSEARCH_USERNAME: ${ELASTICSEARCH_USERNAME:-elastic}
  ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD:-elastic}
  KIBANA_PORT: ${KIBANA_PORT:-5601}
  ELASTICSEARCH_USE_CLOUD: ${ELASTICSEARCH_USE_CLOUD:-false}
  ELASTICSEARCH_CLOUD_URL: ${ELASTICSEARCH_CLOUD_URL:-YOUR-ELASTICSEARCH_CLOUD_URL}
  ELASTICSEARCH_API_KEY: ${ELASTICSEARCH_API_KEY:-YOUR-ELASTICSEARCH_API_KEY}
  ELASTICSEARCH_VERIFY_CERTS: ${ELASTICSEARCH_VERIFY_CERTS:-False}
  ELASTICSEARCH_CA_CERTS: ${ELASTICSEARCH_CA_CERTS:-}
  ELASTICSEARCH_REQUEST_TIMEOUT: ${ELASTICSEARCH_REQUEST_TIMEOUT:-100000}
  ELASTICSEARCH_RETRY_ON_TIMEOUT: ${ELASTICSEARCH_RETRY_ON_TIMEOUT:-True}
  ELASTICSEARCH_MAX_RETRIES: ${ELASTICSEARCH_MAX_RETRIES:-10}
  BAIDU_VECTOR_DB_ENDPOINT: ${BAIDU_VECTOR_DB_ENDPOINT:-http://127.0.0.1:5287}
  BAIDU_VECTOR_DB_CONNECTION_TIMEOUT_MS: ${BAIDU_VECTOR_DB_CONNECTION_TIMEOUT_MS:-30000}
  BAIDU_VECTOR_DB_ACCOUNT: ${BAIDU_VECTOR_DB_ACCOUNT:-root}
  BAIDU_VECTOR_DB_API_KEY: ${BAIDU_VECTOR_DB_API_KEY:-dify}
  BAIDU_VECTOR_DB_DATABASE: ${BAIDU_VECTOR_DB_DATABASE:-dify}
  BAIDU_VECTOR_DB_SHARD: ${BAIDU_VECTOR_DB_SHARD:-1}
  BAIDU_VECTOR_DB_REPLICAS: ${BAIDU_VECTOR_DB_REPLICAS:-3}
  VIKINGDB_ACCESS_KEY: ${VIKINGDB_ACCESS_KEY:-your-ak}
  VIKINGDB_SECRET_KEY: ${VIKINGDB_SECRET_KEY:-your-sk}
  VIKINGDB_REGION: ${VIKINGDB_REGION:-cn-shanghai}
  VIKINGDB_HOST: ${VIKINGDB_HOST:-api-vikingdb.xxx.volces.com}
  VIKINGDB_SCHEMA: ${VIKINGDB_SCHEMA:-http}
  VIKINGDB_CONNECTION_TIMEOUT: ${VIKINGDB_CONNECTION_TIMEOUT:-30}
  VIKINGDB_SOCKET_TIMEOUT: ${VIKINGDB_SOCKET_TIMEOUT:-30}
  LINDORM_URL: ${LINDORM_URL:-http://lindorm:30070}
  LINDORM_USERNAME: ${LINDORM_USERNAME:-lindorm}
  LINDORM_PASSWORD: ${LINDORM_PASSWORD:-lindorm}
  LINDORM_QUERY_TIMEOUT: ${LINDORM_QUERY_TIMEOUT:-1}
  OCEANBASE_VECTOR_HOST: ${OCEANBASE_VECTOR_HOST:-oceanbase}
  OCEANBASE_VECTOR_PORT: ${OCEANBASE_VECTOR_PORT:-2881}
  OCEANBASE_VECTOR_USER: ${OCEANBASE_VECTOR_USER:-root@test}
  OCEANBASE_VECTOR_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
  OCEANBASE_VECTOR_DATABASE: ${OCEANBASE_VECTOR_DATABASE:-test}
  OCEANBASE_CLUSTER_NAME: ${OCEANBASE_CLUSTER_NAME:-difyai}
  OCEANBASE_MEMORY_LIMIT: ${OCEANBASE_MEMORY_LIMIT:-6G}
  OCEANBASE_ENABLE_HYBRID_SEARCH: ${OCEANBASE_ENABLE_HYBRID_SEARCH:-false}
  OPENGAUSS_HOST: ${OPENGAUSS_HOST:-opengauss}
  OPENGAUSS_PORT: ${OPENGAUSS_PORT:-6600}
  OPENGAUSS_USER: ${OPENGAUSS_USER:-postgres}
  OPENGAUSS_PASSWORD: ${OPENGAUSS_PASSWORD:-Dify@123}
  OPENGAUSS_DATABASE: ${OPENGAUSS_DATABASE:-dify}
  OPENGAUSS_MIN_CONNECTION: ${OPENGAUSS_MIN_CONNECTION:-1}
  OPENGAUSS_MAX_CONNECTION: ${OPENGAUSS_MAX_CONNECTION:-5}
  OPENGAUSS_ENABLE_PQ: ${OPENGAUSS_ENABLE_PQ:-false}
  HUAWEI_CLOUD_HOSTS: ${HUAWEI_CLOUD_HOSTS:-https://127.0.0.1:9200}
  HUAWEI_CLOUD_USER: ${HUAWEI_CLOUD_USER:-admin}
  HUAWEI_CLOUD_PASSWORD: ${HUAWEI_CLOUD_PASSWORD:-admin}
  UPSTASH_VECTOR_URL: ${UPSTASH_VECTOR_URL:-https://xxx-vector.upstash.io}
  UPSTASH_VECTOR_TOKEN: ${UPSTASH_VECTOR_TOKEN:-dify}
  TABLESTORE_ENDPOINT: ${TABLESTORE_ENDPOINT:-https://instance-name.cn-hangzhou.ots.aliyuncs.com}
  TABLESTORE_INSTANCE_NAME: ${TABLESTORE_INSTANCE_NAME:-instance-name}
  TABLESTORE_ACCESS_KEY_ID: ${TABLESTORE_ACCESS_KEY_ID:-xxx}
  TABLESTORE_ACCESS_KEY_SECRET: ${TABLESTORE_ACCESS_KEY_SECRET:-xxx}
  TABLESTORE_NORMALIZE_FULLTEXT_BM25_SCORE: ${TABLESTORE_NORMALIZE_FULLTEXT_BM25_SCORE:-false}
  CLICKZETTA_USERNAME: ${CLICKZETTA_USERNAME:-}
  CLICKZETTA_PASSWORD: ${CLICKZETTA_PASSWORD:-}
  CLICKZETTA_INSTANCE: ${CLICKZETTA_INSTANCE:-}
  CLICKZETTA_SERVICE: ${CLICKZETTA_SERVICE:-api.clickzetta.com}
  CLICKZETTA_WORKSPACE: ${CLICKZETTA_WORKSPACE:-quick_start}
  CLICKZETTA_VCLUSTER: ${CLICKZETTA_VCLUSTER:-default_ap}
  CLICKZETTA_SCHEMA: ${CLICKZETTA_SCHEMA:-dify}
  CLICKZETTA_BATCH_SIZE: ${CLICKZETTA_BATCH_SIZE:-100}
  CLICKZETTA_ENABLE_INVERTED_INDEX: ${CLICKZETTA_ENABLE_INVERTED_INDEX:-true}
  CLICKZETTA_ANALYZER_TYPE: ${CLICKZETTA_ANALYZER_TYPE:-chinese}
  CLICKZETTA_ANALYZER_MODE: ${CLICKZETTA_ANALYZER_MODE:-smart}
  CLICKZETTA_VECTOR_DISTANCE_FUNCTION: ${CLICKZETTA_VECTOR_DISTANCE_FUNCTION:-cosine_distance}
  UPLOAD_FILE_SIZE_LIMIT: ${UPLOAD_FILE_SIZE_LIMIT:-15}
  UPLOAD_FILE_BATCH_LIMIT: ${UPLOAD_FILE_BATCH_LIMIT:-5}
  ETL_TYPE: ${ETL_TYPE:-dify}
  UNSTRUCTURED_API_URL: ${UNSTRUCTURED_API_URL:-}
  UNSTRUCTURED_API_KEY: ${UNSTRUCTURED_API_KEY:-}
  SCARF_NO_ANALYTICS: ${SCARF_NO_ANALYTICS:-true}
  PROMPT_GENERATION_MAX_TOKENS: ${PROMPT_GENERATION_MAX_TOKENS:-512}
  CODE_GENERATION_MAX_TOKENS: ${CODE_GENERATION_MAX_TOKENS:-1024}
  PLUGIN_BASED_TOKEN_COUNTING_ENABLED: ${PLUGIN_BASED_TOKEN_COUNTING_ENABLED:-false}
  MULTIMODAL_SEND_FORMAT: ${MULTIMODAL_SEND_FORMAT:-base64}
  UPLOAD_IMAGE_FILE_SIZE_LIMIT: ${UPLOAD_IMAGE_FILE_SIZE_LIMIT:-10}
  UPLOAD_VIDEO_FILE_SIZE_LIMIT: ${UPLOAD_VIDEO_FILE_SIZE_LIMIT:-100}
  UPLOAD_AUDIO_FILE_SIZE_LIMIT: ${UPLOAD_AUDIO_FILE_SIZE_LIMIT:-50}
  SENTRY_DSN: ${SENTRY_DSN:-}
  API_SENTRY_DSN: ${API_SENTRY_DSN:-}
  API_SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
  API_SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
  WEB_SENTRY_DSN: ${WEB_SENTRY_DSN:-}
  NOTION_INTEGRATION_TYPE: ${NOTION_INTEGRATION_TYPE:-public}
  NOTION_CLIENT_SECRET: ${NOTION_CLIENT_SECRET:-}
  NOTION_CLIENT_ID: ${NOTION_CLIENT_ID:-}
  NOTION_INTERNAL_SECRET: ${NOTION_INTERNAL_SECRET:-}
  MAIL_TYPE: ${MAIL_TYPE:-resend}
  MAIL_DEFAULT_SEND_FROM: ${MAIL_DEFAULT_SEND_FROM:-}
  RESEND_API_URL: ${RESEND_API_URL:-https://api.resend.com}
  RESEND_API_KEY: ${RESEND_API_KEY:-your-resend-api-key}
  SMTP_SERVER: ${SMTP_SERVER:-}
  SMTP_PORT: ${SMTP_PORT:-465}
  SMTP_USERNAME: ${SMTP_USERNAME:-}
  SMTP_PASSWORD: ${SMTP_PASSWORD:-}
  SMTP_USE_TLS: ${SMTP_USE_TLS:-true}
  SMTP_OPPORTUNISTIC_TLS: ${SMTP_OPPORTUNISTIC_TLS:-false}
  SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
  INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: ${INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH:-4000}
  INVITE_EXPIRY_HOURS: ${INVITE_EXPIRY_HOURS:-72}
  RESET_PASSWORD_TOKEN_EXPIRY_MINUTES: ${RESET_PASSWORD_TOKEN_EXPIRY_MINUTES:-5}
  CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES: ${CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES:-5}
  OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES: ${OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES:-5}
  CODE_EXECUTION_ENDPOINT: ${CODE_EXECUTION_ENDPOINT:-http://sandbox:8194}
  CODE_EXECUTION_API_KEY: ${CODE_EXECUTION_API_KEY:-dify-sandbox}
  CODE_MAX_NUMBER: ${CODE_MAX_NUMBER:-9223372036854775807}
  CODE_MIN_NUMBER: ${CODE_MIN_NUMBER:--9223372036854775808}
  CODE_MAX_DEPTH: ${CODE_MAX_DEPTH:-5}
  CODE_MAX_PRECISION: ${CODE_MAX_PRECISION:-20}
  CODE_MAX_STRING_LENGTH: ${CODE_MAX_STRING_LENGTH:-80000}
  CODE_MAX_STRING_ARRAY_LENGTH: ${CODE_MAX_STRING_ARRAY_LENGTH:-30}
  CODE_MAX_OBJECT_ARRAY_LENGTH: ${CODE_MAX_OBJECT_ARRAY_LENGTH:-30}
  CODE_MAX_NUMBER_ARRAY_LENGTH: ${CODE_MAX_NUMBER_ARRAY_LENGTH:-1000}
  CODE_EXECUTION_CONNECT_TIMEOUT: ${CODE_EXECUTION_CONNECT_TIMEOUT:-10}
  CODE_EXECUTION_READ_TIMEOUT: ${CODE_EXECUTION_READ_TIMEOUT:-60}
  CODE_EXECUTION_WRITE_TIMEOUT: ${CODE_EXECUTION_WRITE_TIMEOUT:-10}
  TEMPLATE_TRANSFORM_MAX_LENGTH: ${TEMPLATE_TRANSFORM_MAX_LENGTH:-80000}
  WORKFLOW_MAX_EXECUTION_STEPS: ${WORKFLOW_MAX_EXECUTION_STEPS:-500}
  WORKFLOW_MAX_EXECUTION_TIME: ${WORKFLOW_MAX_EXECUTION_TIME:-1200}
  WORKFLOW_CALL_MAX_DEPTH: ${WORKFLOW_CALL_MAX_DEPTH:-5}
  MAX_VARIABLE_SIZE: ${MAX_VARIABLE_SIZE:-204800}
  WORKFLOW_PARALLEL_DEPTH_LIMIT: ${WORKFLOW_PARALLEL_DEPTH_LIMIT:-3}
  WORKFLOW_FILE_UPLOAD_LIMIT: ${WORKFLOW_FILE_UPLOAD_LIMIT:-10}
  WORKFLOW_NODE_EXECUTION_STORAGE: ${WORKFLOW_NODE_EXECUTION_STORAGE:-rdbms}
  CORE_WORKFLOW_EXECUTION_REPOSITORY: ${CORE_WORKFLOW_EXECUTION_REPOSITORY:-core.repositories.sqlalchemy_workflow_execution_repository.SQLAlchemyWorkflowExecutionRepository}
  CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY: ${CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY:-core.repositories.sqlalchemy_workflow_node_execution_repository.SQLAlchemyWorkflowNodeExecutionRepository}
  API_WORKFLOW_RUN_REPOSITORY: ${API_WORKFLOW_RUN_REPOSITORY:-repositories.sqlalchemy_api_workflow_run_repository.DifyAPISQLAlchemyWorkflowRunRepository}
  API_WORKFLOW_NODE_EXECUTION_REPOSITORY: ${API_WORKFLOW_NODE_EXECUTION_REPOSITORY:-repositories.sqlalchemy_api_workflow_node_execution_repository.DifyAPISQLAlchemyWorkflowNodeExecutionRepository}
  WORKFLOW_LOG_CLEANUP_ENABLED: ${WORKFLOW_LOG_CLEANUP_ENABLED:-false}
  WORKFLOW_LOG_RETENTION_DAYS: ${WORKFLOW_LOG_RETENTION_DAYS:-30}
  WORKFLOW_LOG_CLEANUP_BATCH_SIZE: ${WORKFLOW_LOG_CLEANUP_BATCH_SIZE:-100}
  HTTP_REQUEST_NODE_MAX_BINARY_SIZE: ${HTTP_REQUEST_NODE_MAX_BINARY_SIZE:-10485760}
  HTTP_REQUEST_NODE_MAX_TEXT_SIZE: ${HTTP_REQUEST_NODE_MAX_TEXT_SIZE:-1048576}
  HTTP_REQUEST_NODE_SSL_VERIFY: ${HTTP_REQUEST_NODE_SSL_VERIFY:-True}
  RESPECT_XFORWARD_HEADERS_ENABLED: ${RESPECT_XFORWARD_HEADERS_ENABLED:-false}
  SSRF_PROXY_HTTP_URL: ${SSRF_PROXY_HTTP_URL:-http://ssrf_proxy:3128}
  SSRF_PROXY_HTTPS_URL: ${SSRF_PROXY_HTTPS_URL:-http://ssrf_proxy:3128}
  LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
  MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
  MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
  MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
  TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000}
  ALLOW_UNSAFE_DATA_SCHEME: ${ALLOW_UNSAFE_DATA_SCHEME:-false}
  MAX_TREE_DEPTH: ${MAX_TREE_DEPTH:-50}
  POSTGRES_USER: ${POSTGRES_USER:-${DB_USERNAME}}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-${DB_PASSWORD}}
  POSTGRES_DB: ${POSTGRES_DB:-${DB_DATABASE}}
  PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
  SANDBOX_API_KEY: ${SANDBOX_API_KEY:-dify-sandbox}
  SANDBOX_GIN_MODE: ${SANDBOX_GIN_MODE:-release}
  SANDBOX_WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15}
  SANDBOX_ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true}
  SANDBOX_HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
  SANDBOX_HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
  SANDBOX_PORT: ${SANDBOX_PORT:-8194}
  WEAVIATE_PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate}
  WEAVIATE_QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25}
  WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-true}
  WEAVIATE_DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none}
  WEAVIATE_CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1}
  WEAVIATE_AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true}
  WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih}
  WEAVIATE_AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
  WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
  WEAVIATE_AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}
  CHROMA_SERVER_AUTHN_CREDENTIALS: ${CHROMA_SERVER_AUTHN_CREDENTIALS:-difyai123456}
  CHROMA_SERVER_AUTHN_PROVIDER: ${CHROMA_SERVER_AUTHN_PROVIDER:-chromadb.auth.token_authn.TokenAuthenticationServerProvider}
  CHROMA_IS_PERSISTENT: ${CHROMA_IS_PERSISTENT:-TRUE}
  ORACLE_PWD: ${ORACLE_PWD:-Dify123456}
  ORACLE_CHARACTERSET: ${ORACLE_CHARACTERSET:-AL32UTF8}
  ETCD_AUTO_COMPACTION_MODE: ${ETCD_AUTO_COMPACTION_MODE:-revision}
  ETCD_AUTO_COMPACTION_RETENTION: ${ETCD_AUTO_COMPACTION_RETENTION:-1000}
  ETCD_QUOTA_BACKEND_BYTES: ${ETCD_QUOTA_BACKEND_BYTES:-4294967296}
  ETCD_SNAPSHOT_COUNT: ${ETCD_SNAPSHOT_COUNT:-50000}
  MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
  MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
  ETCD_ENDPOINTS: ${ETCD_ENDPOINTS:-etcd:2379}
  MINIO_ADDRESS: ${MINIO_ADDRESS:-minio:9000}
  MILVUS_AUTHORIZATION_ENABLED: ${MILVUS_AUTHORIZATION_ENABLED:-true}
  PGVECTOR_PGUSER: ${PGVECTOR_PGUSER:-postgres}
  PGVECTOR_POSTGRES_PASSWORD: ${PGVECTOR_POSTGRES_PASSWORD:-difyai123456}
  PGVECTOR_POSTGRES_DB: ${PGVECTOR_POSTGRES_DB:-dify}
  PGVECTOR_PGDATA: ${PGVECTOR_PGDATA:-/var/lib/postgresql/data/pgdata}
  OPENSEARCH_DISCOVERY_TYPE: ${OPENSEARCH_DISCOVERY_TYPE:-single-node}
  OPENSEARCH_BOOTSTRAP_MEMORY_LOCK: ${OPENSEARCH_BOOTSTRAP_MEMORY_LOCK:-true}
  OPENSEARCH_JAVA_OPTS_MIN: ${OPENSEARCH_JAVA_OPTS_MIN:-512m}
  OPENSEARCH_JAVA_OPTS_MAX: ${OPENSEARCH_JAVA_OPTS_MAX:-1024m}
  OPENSEARCH_INITIAL_ADMIN_PASSWORD: ${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-Qazwsxedc!@#123}
  OPENSEARCH_MEMLOCK_SOFT: ${OPENSEARCH_MEMLOCK_SOFT:--1}
  OPENSEARCH_MEMLOCK_HARD: ${OPENSEARCH_MEMLOCK_HARD:--1}
  OPENSEARCH_NOFILE_SOFT: ${OPENSEARCH_NOFILE_SOFT:-65536}
  OPENSEARCH_NOFILE_HARD: ${OPENSEARCH_NOFILE_HARD:-65536}
  NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_}
  NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false}
  NGINX_PORT: ${NGINX_PORT:-80}
  NGINX_SSL_PORT: ${NGINX_SSL_PORT:-443}
  NGINX_SSL_CERT_FILENAME: ${NGINX_SSL_CERT_FILENAME:-dify.crt}
  NGINX_SSL_CERT_KEY_FILENAME: ${NGINX_SSL_CERT_KEY_FILENAME:-dify.key}
  NGINX_SSL_PROTOCOLS: ${NGINX_SSL_PROTOCOLS:-TLSv1.1 TLSv1.2 TLSv1.3}
  NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto}
  NGINX_CLIENT_MAX_BODY_SIZE: ${NGINX_CLIENT_MAX_BODY_SIZE:-100M}
  NGINX_KEEPALIVE_TIMEOUT: ${NGINX_KEEPALIVE_TIMEOUT:-65}
  NGINX_PROXY_READ_TIMEOUT: ${NGINX_PROXY_READ_TIMEOUT:-3600s}
  NGINX_PROXY_SEND_TIMEOUT: ${NGINX_PROXY_SEND_TIMEOUT:-3600s}
  NGINX_ENABLE_CERTBOT_CHALLENGE: ${NGINX_ENABLE_CERTBOT_CHALLENGE:-false}
  CERTBOT_EMAIL: ${CERTBOT_EMAIL:-your_email@example.com}
  CERTBOT_DOMAIN: ${CERTBOT_DOMAIN:-your_domain.com}
  CERTBOT_OPTIONS: ${CERTBOT_OPTIONS:-}
  SSRF_HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
  SSRF_COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid}
  SSRF_REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194}
  SSRF_SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox}
  SSRF_DEFAULT_TIME_OUT: ${SSRF_DEFAULT_TIME_OUT:-5}
  SSRF_DEFAULT_CONNECT_TIME_OUT: ${SSRF_DEFAULT_CONNECT_TIME_OUT:-5}
  SSRF_DEFAULT_READ_TIME_OUT: ${SSRF_DEFAULT_READ_TIME_OUT:-5}
  SSRF_DEFAULT_WRITE_TIME_OUT: ${SSRF_DEFAULT_WRITE_TIME_OUT:-5}
  EXPOSE_NGINX_PORT: ${EXPOSE_NGINX_PORT:-80}
  EXPOSE_NGINX_SSL_PORT: ${EXPOSE_NGINX_SSL_PORT:-443}
  POSITION_TOOL_PINS: ${POSITION_TOOL_PINS:-}
  POSITION_TOOL_INCLUDES: ${POSITION_TOOL_INCLUDES:-}
  POSITION_TOOL_EXCLUDES: ${POSITION_TOOL_EXCLUDES:-}
  POSITION_PROVIDER_PINS: ${POSITION_PROVIDER_PINS:-}
  POSITION_PROVIDER_INCLUDES: ${POSITION_PROVIDER_INCLUDES:-}
  POSITION_PROVIDER_EXCLUDES: ${POSITION_PROVIDER_EXCLUDES:-}
  CSP_WHITELIST: ${CSP_WHITELIST:-}
  CREATE_TIDB_SERVICE_JOB_ENABLED: ${CREATE_TIDB_SERVICE_JOB_ENABLED:-false}
  MAX_SUBMIT_COUNT: ${MAX_SUBMIT_COUNT:-100}
  TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-10}
  DB_PLUGIN_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
  EXPOSE_PLUGIN_DAEMON_PORT: ${EXPOSE_PLUGIN_DAEMON_PORT:-5002}
  PLUGIN_DAEMON_PORT: ${PLUGIN_DAEMON_PORT:-5002}
  PLUGIN_DAEMON_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
  PLUGIN_DAEMON_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002}
  PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
  PLUGIN_PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
  PLUGIN_DEBUGGING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
  PLUGIN_DEBUGGING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
  EXPOSE_PLUGIN_DEBUGGING_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost}
  EXPOSE_PLUGIN_DEBUGGING_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}
  PLUGIN_DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
  PLUGIN_DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001}
  ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}}
  MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true}
  MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai}
  FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true}
  PLUGIN_STDIO_BUFFER_SIZE: ${PLUGIN_STDIO_BUFFER_SIZE:-1024}
  PLUGIN_STDIO_MAX_BUFFER_SIZE: ${PLUGIN_STDIO_MAX_BUFFER_SIZE:-5242880}
  PLUGIN_PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
  PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
  PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
  PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
  PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
  PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
  PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
  PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
  PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
  PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
  PLUGIN_S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
  PLUGIN_S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
  PLUGIN_S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
  PLUGIN_S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
  PLUGIN_AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
  PLUGIN_AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
  PLUGIN_AWS_REGION: ${PLUGIN_AWS_REGION:-}
  PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
  PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
  PLUGIN_TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
  PLUGIN_TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
  PLUGIN_TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
  PLUGIN_ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
  PLUGIN_ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
  PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
  PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
  PLUGIN_ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
  PLUGIN_ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
  PLUGIN_VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
  PLUGIN_VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
  PLUGIN_VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
  PLUGIN_VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
  ENABLE_OTEL: ${ENABLE_OTEL:-false}
  OTLP_TRACE_ENDPOINT: ${OTLP_TRACE_ENDPOINT:-}
  OTLP_METRIC_ENDPOINT: ${OTLP_METRIC_ENDPOINT:-}
  OTLP_BASE_ENDPOINT: ${OTLP_BASE_ENDPOINT:-http://localhost:4318}
  OTLP_API_KEY: ${OTLP_API_KEY:-}
  OTEL_EXPORTER_OTLP_PROTOCOL: ${OTEL_EXPORTER_OTLP_PROTOCOL:-}
  OTEL_EXPORTER_TYPE: ${OTEL_EXPORTER_TYPE:-otlp}
  OTEL_SAMPLING_RATE: ${OTEL_SAMPLING_RATE:-0.1}
  OTEL_BATCH_EXPORT_SCHEDULE_DELAY: ${OTEL_BATCH_EXPORT_SCHEDULE_DELAY:-5000}
  OTEL_MAX_QUEUE_SIZE: ${OTEL_MAX_QUEUE_SIZE:-2048}
  OTEL_MAX_EXPORT_BATCH_SIZE: ${OTEL_MAX_EXPORT_BATCH_SIZE:-512}
  OTEL_METRIC_EXPORT_INTERVAL: ${OTEL_METRIC_EXPORT_INTERVAL:-60000}
  OTEL_BATCH_EXPORT_TIMEOUT: ${OTEL_BATCH_EXPORT_TIMEOUT:-10000}
  OTEL_METRIC_EXPORT_TIMEOUT: ${OTEL_METRIC_EXPORT_TIMEOUT:-30000}
  ALLOW_EMBED: ${ALLOW_EMBED:-false}
  QUEUE_MONITOR_THRESHOLD: ${QUEUE_MONITOR_THRESHOLD:-200}
  QUEUE_MONITOR_ALERT_EMAILS: ${QUEUE_MONITOR_ALERT_EMAILS:-}
  QUEUE_MONITOR_INTERVAL: ${QUEUE_MONITOR_INTERVAL:-30}
  SWAGGER_UI_ENABLED: ${SWAGGER_UI_ENABLED:-true}
  SWAGGER_UI_PATH: ${SWAGGER_UI_PATH:-/swagger-ui.html}
  ENABLE_CLEAN_EMBEDDING_CACHE_TASK: ${ENABLE_CLEAN_EMBEDDING_CACHE_TASK:-false}
  ENABLE_CLEAN_UNUSED_DATASETS_TASK: ${ENABLE_CLEAN_UNUSED_DATASETS_TASK:-false}
  ENABLE_CREATE_TIDB_SERVERLESS_TASK: ${ENABLE_CREATE_TIDB_SERVERLESS_TASK:-false}
  ENABLE_UPDATE_TIDB_SERVERLESS_STATUS_TASK: ${ENABLE_UPDATE_TIDB_SERVERLESS_STATUS_TASK:-false}
  ENABLE_CLEAN_MESSAGES: ${ENABLE_CLEAN_MESSAGES:-false}
  ENABLE_MAIL_CLEAN_DOCUMENT_NOTIFY_TASK: ${ENABLE_MAIL_CLEAN_DOCUMENT_NOTIFY_TASK:-false}
  ENABLE_DATASETS_QUEUE_MONITOR: ${ENABLE_DATASETS_QUEUE_MONITOR:-false}
  ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK: ${ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK:-true}

services:
  # API service
  api:
    image: langgenius/dify-api:1.8.0
    restart: always
    environment:
      # Use the shared environment variables.
      &lt;&lt;: *shared-api-worker-env
      # Startup mode, 'api' starts the API server.
      MODE: api
      SENTRY_DSN: ${API_SENTRY_DSN:-}
      SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
      SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
      PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost}
      PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}
      PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
      INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      # Mount the storage directory to the container, for storing user files.
      - ./volumes/app/storage:/app/api/storage
    networks:
      - ssrf_proxy_network
      - default

  # worker service
  # The Celery worker for processing the queue.
  worker:
    image: langgenius/dify-api:1.8.0
    restart: always
    environment:
      # Use the shared environment variables.
      &lt;&lt;: *shared-api-worker-env
      # Startup mode, 'worker' starts the Celery worker for processing the queue.
      MODE: worker
      SENTRY_DSN: ${API_SENTRY_DSN:-}
      SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
      SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
      PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
      INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      # Mount the storage directory to the container, for storing user files.
      - ./volumes/app/storage:/app/api/storage
    networks:
      - ssrf_proxy_network
      - default

  # worker_beat service
  # Celery beat for scheduling periodic tasks.
  worker_beat:
    image: langgenius/dify-api:1.8.0
    restart: always
    environment:
      # Use the shared environment variables.
      &lt;&lt;: *shared-api-worker-env
      # Startup mode, 'worker_beat' starts the Celery beat for scheduling periodic tasks.
      MODE: beat
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - ssrf_proxy_network
      - default

  # Frontend web application.
  web:
    image: langgenius/dify-web:1.8.0
    restart: always
    environment:
      CONSOLE_API_URL: ${CONSOLE_API_URL:-}
      APP_API_URL: ${APP_API_URL:-}
      SENTRY_DSN: ${WEB_SENTRY_DSN:-}
      NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0}
      TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000}
      CSP_WHITELIST: ${CSP_WHITELIST:-}
      ALLOW_EMBED: ${ALLOW_EMBED:-false}
      ALLOW_UNSAFE_DATA_SCHEME: ${ALLOW_UNSAFE_DATA_SCHEME:-false}
      MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai}
      MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace.dify.ai}
      TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-}
      INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: ${INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH:-}
      PM2_INSTANCES: ${PM2_INSTANCES:-2}
      LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
      MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
      MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
      MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
      MAX_TREE_DEPTH: ${MAX_TREE_DEPTH:-50}
      ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
      ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
      ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}
  # The postgres database.
  db:
    image: postgres:15-alpine
    restart: always
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456}
      POSTGRES_DB: ${POSTGRES_DB:-dify}
      PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
    command: &gt;
      postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}'
               -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}'
               -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}'
               -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}'
               -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}'
    volumes:
      - ./volumes/db/data:/var/lib/postgresql/data
    healthcheck:
      test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ]
      interval: 1s
      timeout: 3s
      retries: 60

  # The redis cache.
  redis:
    image: redis:6-alpine
    restart: always
    environment:
      REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456}
    volumes:
      # Mount the redis data directory to the container.
      - ./volumes/redis/data:/data
    # Set the redis password when startup redis server.
    command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456}
    healthcheck:
      test: [ 'CMD', 'redis-cli', 'ping' ]

  # The DifySandbox
  sandbox:
    image: langgenius/dify-sandbox:0.2.12
    restart: always
    environment:
      # The DifySandbox configurations
      # Make sure you are changing this key for your deployment with a strong key.
      # You can generate a strong key using `openssl rand -base64 42`.
      API_KEY: ${SANDBOX_API_KEY:-dify-sandbox}
      GIN_MODE: ${SANDBOX_GIN_MODE:-release}
      WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15}
      ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true}
      HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
      HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
      SANDBOX_PORT: ${SANDBOX_PORT:-8194}
      PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
    volumes:
      - ./volumes/sandbox/dependencies:/dependencies
      - ./volumes/sandbox/conf:/conf
    healthcheck:
      test: [ 'CMD', 'curl', '-f', 'http://localhost:8194/health' ]
    networks:
      - ssrf_proxy_network

  # plugin daemon
  plugin_daemon:
    image: langgenius/dify-plugin-daemon:0.2.0-local
    restart: always
    environment:
      # Use the shared environment variables.
      &lt;&lt;: *shared-api-worker-env
      DB_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
      SERVER_PORT: ${PLUGIN_DAEMON_PORT:-5002}
      SERVER_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
      MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
      PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
      DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001}
      DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
      PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
      PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
      PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
      FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true}
      PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
      PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
      PLUGIN_STDIO_BUFFER_SIZE: ${PLUGIN_STDIO_BUFFER_SIZE:-1024}
      PLUGIN_STDIO_MAX_BUFFER_SIZE: ${PLUGIN_STDIO_MAX_BUFFER_SIZE:-5242880}
      PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
      PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
      PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
      PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
      PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
      PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
      PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
      S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
      S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
      S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
      S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
      AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
      AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
      AWS_REGION: ${PLUGIN_AWS_REGION:-}
      AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
      AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
      TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
      TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
      TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
      ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
      ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
      ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
      ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
      ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
      ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
      VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
      VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
      VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
      VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
    ports:
      - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
    volumes:
      - ./volumes/plugin_daemon:/app/storage
    depends_on:
      db:
        condition: service_healthy

  # ssrf_proxy server
  # for more information, please refer to
  # https://docs.dify.ai/learn-more/faq/install-faq#18-why-is-ssrf-proxy-needed%3F
  ssrf_proxy:
    image: ubuntu/squid:latest
    restart: always
    volumes:
      - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template
      - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh
    entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh &amp;&amp; sed -i 's/\r$$//' /docker-entrypoint.sh &amp;&amp; chmod +x /docker-entrypoint.sh &amp;&amp; /docker-entrypoint.sh" ]
    environment:
      # pls clearly modify the squid env vars to fit your network environment.
      HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
      COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid}
      REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194}
      SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox}
      SANDBOX_PORT: ${SANDBOX_PORT:-8194}
    networks:
      - ssrf_proxy_network
      - default

  # Certbot service
  # use `docker-compose --profile certbot up` to start the certbot service.
  certbot:
    image: certbot/certbot
    profiles:
      - certbot
    volumes:
      - ./volumes/certbot/conf:/etc/letsencrypt
      - ./volumes/certbot/www:/var/www/html
      - ./volumes/certbot/logs:/var/log/letsencrypt
      - ./volumes/certbot/conf/live:/etc/letsencrypt/live
      - ./certbot/update-cert.template.txt:/update-cert.template.txt
      - ./certbot/docker-entrypoint.sh:/docker-entrypoint.sh
    environment:
      - CERTBOT_EMAIL=${CERTBOT_EMAIL}
      - CERTBOT_DOMAIN=${CERTBOT_DOMAIN}
      - CERTBOT_OPTIONS=${CERTBOT_OPTIONS:-}
    entrypoint: [ '/docker-entrypoint.sh' ]
    command: [ 'tail', '-f', '/dev/null' ]

  # The nginx reverse proxy.
  # used for reverse proxying the API service and Web service.
  nginx:
    image: nginx:latest
    restart: always
    volumes:
      - ./nginx/nginx.conf.template:/etc/nginx/nginx.conf.template
      - ./nginx/proxy.conf.template:/etc/nginx/proxy.conf.template
      - ./nginx/https.conf.template:/etc/nginx/https.conf.template
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/docker-entrypoint.sh:/docker-entrypoint-mount.sh
      - ./nginx/ssl:/etc/ssl # cert dir (legacy)
      - ./volumes/certbot/conf/live:/etc/letsencrypt/live # cert dir (with certbot container)
      - ./volumes/certbot/conf:/etc/letsencrypt
      - ./volumes/certbot/www:/var/www/html
    entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh &amp;&amp; sed -i 's/\r$$//' /docker-entrypoint.sh &amp;&amp; chmod +x /docker-entrypoint.sh &amp;&amp; /docker-entrypoint.sh" ]
    environment:
      NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_}
      NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false}
      NGINX_SSL_PORT: ${NGINX_SSL_PORT:-443}
      NGINX_PORT: ${NGINX_PORT:-80}
      # You're required to add your own SSL certificates/keys to the `./nginx/ssl` directory
      # and modify the env vars below in .env if HTTPS_ENABLED is true.
      NGINX_SSL_CERT_FILENAME: ${NGINX_SSL_CERT_FILENAME:-dify.crt}
      NGINX_SSL_CERT_KEY_FILENAME: ${NGINX_SSL_CERT_KEY_FILENAME:-dify.key}
      NGINX_SSL_PROTOCOLS: ${NGINX_SSL_PROTOCOLS:-TLSv1.1 TLSv1.2 TLSv1.3}
      NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto}
      NGINX_CLIENT_MAX_BODY_SIZE: ${NGINX_CLIENT_MAX_BODY_SIZE:-100M}
      NGINX_KEEPALIVE_TIMEOUT: ${NGINX_KEEPALIVE_TIMEOUT:-65}
      NGINX_PROXY_READ_TIMEOUT: ${NGINX_PROXY_READ_TIMEOUT:-3600s}
      NGINX_PROXY_SEND_TIMEOUT: ${NGINX_PROXY_SEND_TIMEOUT:-3600s}
      NGINX_ENABLE_CERTBOT_CHALLENGE: ${NGINX_ENABLE_CERTBOT_CHALLENGE:-false}
      CERTBOT_DOMAIN: ${CERTBOT_DOMAIN:-}
    depends_on:
      - api
      - web
    ports:
      - '${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}'
      - '${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}'

  # The Weaviate vector store.
  weaviate:
    image: semitechnologies/weaviate:1.19.0
    profiles:
      - ''
      - weaviate
    restart: always
    volumes:
      # Mount the Weaviate data directory to the con tainer.
      - ./volumes/weaviate:/var/lib/weaviate
    environment:
      # The Weaviate configurations
      # You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information.
      PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate}
      QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25}
      AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false}
      DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none}
      CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1}
      AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true}
      AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih}
      AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
      AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
      AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}

  # Qdrant vector store.
  # (if used, you need to set VECTOR_STORE to qdrant in the api &amp; worker service.)
  qdrant:
    image: langgenius/qdrant:v1.7.3
    profiles:
      - qdrant
    restart: always
    volumes:
      - ./volumes/qdrant:/qdrant/storage
    environment:
      QDRANT_API_KEY: ${QDRANT_API_KEY:-difyai123456}

  # The Couchbase vector store.
  couchbase-server:
    build: ./couchbase-server
    profiles:
      - couchbase
    restart: always
    environment:
      - CLUSTER_NAME=dify_search
      - COUCHBASE_ADMINISTRATOR_USERNAME=${COUCHBASE_USER:-Administrator}
      - COUCHBASE_ADMINISTRATOR_PASSWORD=${COUCHBASE_PASSWORD:-password}
      - COUCHBASE_BUCKET=${COUCHBASE_BUCKET_NAME:-Embeddings}
      - COUCHBASE_BUCKET_RAMSIZE=512
      - COUCHBASE_RAM_SIZE=2048
      - COUCHBASE_EVENTING_RAM_SIZE=512
      - COUCHBASE_INDEX_RAM_SIZE=512
      - COUCHBASE_FTS_RAM_SIZE=1024
    hostname: couchbase-server
    container_name: couchbase-server
    working_dir: /opt/couchbase
    stdin_open: true
    tty: true
    entrypoint: [ "" ]
    command: sh -c "/opt/couchbase/init/init-cbserver.sh"
    volumes:
      - ./volumes/couchbase/data:/opt/couchbase/var/lib/couchbase/data
    healthcheck:
      # ensure bucket was created before proceeding
      test: [ "CMD-SHELL", "curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1" ]
      interval: 10s
      retries: 10
      start_period: 30s
      timeout: 10s

  # The pgvector vector database.
  pgvector:
    image: pgvector/pgvector:pg16
    profiles:
      - pgvector
    restart: always
    environment:
      PGUSER: ${PGVECTOR_PGUSER:-postgres}
      # The password for the default postgres user.
      POSTGRES_PASSWORD: ${PGVECTOR_POSTGRES_PASSWORD:-difyai123456}
      # The name of the default postgres database.
      POSTGRES_DB: ${PGVECTOR_POSTGRES_DB:-dify}
      # postgres data directory
      PGDATA: ${PGVECTOR_PGDATA:-/var/lib/postgresql/data/pgdata}
      # pg_bigm module for full text search
      PG_BIGM: ${PGVECTOR_PG_BIGM:-false}
      PG_BIGM_VERSION: ${PGVECTOR_PG_BIGM_VERSION:-1.2-20240606}
    volumes:
      - ./volumes/pgvector/data:/var/lib/postgresql/data
      - ./pgvector/docker-entrypoint.sh:/docker-entrypoint.sh
    entrypoint: [ '/docker-entrypoint.sh' ]
    healthcheck:
      test: [ 'CMD', 'pg_isready' ]
      interval: 1s
      timeout: 3s
      retries: 30

  # get image from https://www.vastdata.com.cn/
  vastbase:
    image: vastdata/vastbase-vector
    profiles:
      - vastbase
    restart: always
    environment:
      - VB_DBCOMPATIBILITY=PG
      - VB_DB=dify
      - VB_USERNAME=dify
      - VB_PASSWORD=Difyai123456
    ports:
      - '5434:5432'
    volumes:
      - ./vastbase/lic:/home/vastbase/vastbase/lic
      - ./vastbase/data:/home/vastbase/data
      - ./vastbase/backup:/home/vastbase/backup
      - ./vastbase/backup_log:/home/vastbase/backup_log
    healthcheck:
      test: [ 'CMD', 'pg_isready' ]
      interval: 1s
      timeout: 3s
      retries: 30

  # pgvecto-rs vector store
  pgvecto-rs:
    image: tensorchord/pgvecto-rs:pg16-v0.3.0
    profiles:
      - pgvecto-rs
    restart: always
    environment:
      PGUSER: ${PGVECTOR_PGUSER:-postgres}
      # The password for the default postgres user.
      POSTGRES_PASSWORD: ${PGVECTOR_POSTGRES_PASSWORD:-difyai123456}
      # The name of the default postgres database.
      POSTGRES_DB: ${PGVECTOR_POSTGRES_DB:-dify}
      # postgres data directory
      PGDATA: ${PGVECTOR_PGDATA:-/var/lib/postgresql/data/pgdata}
    volumes:
      - ./volumes/pgvecto_rs/data:/var/lib/postgresql/data
    healthcheck:
      test: [ 'CMD', 'pg_isready' ]
      interval: 1s
      timeout: 3s
      retries: 30

  # Chroma vector database
  chroma:
    image: ghcr.io/chroma-core/chroma:0.5.20
    profiles:
      - chroma
    restart: always
    volumes:
      - ./volumes/chroma:/chroma/chroma
    environment:
      CHROMA_SERVER_AUTHN_CREDENTIALS: ${CHROMA_SERVER_AUTHN_CREDENTIALS:-difyai123456}
      CHROMA_SERVER_AUTHN_PROVIDER: ${CHROMA_SERVER_AUTHN_PROVIDER:-chromadb.auth.token_authn.TokenAuthenticationServerProvider}
      IS_PERSISTENT: ${CHROMA_IS_PERSISTENT:-TRUE}

  # OceanBase vector database
  oceanbase:
    image: oceanbase/oceanbase-ce:4.3.5-lts
    container_name: oceanbase
    profiles:
      - oceanbase
    restart: always
    volumes:
      - ./volumes/oceanbase/data:/root/ob
      - ./volumes/oceanbase/conf:/root/.obd/cluster
      - ./volumes/oceanbase/init.d:/root/boot/init.d
    environment:
      OB_MEMORY_LIMIT: ${OCEANBASE_MEMORY_LIMIT:-6G}
      OB_SYS_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
      OB_TENANT_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
      OB_CLUSTER_NAME: ${OCEANBASE_CLUSTER_NAME:-difyai}
      OB_SERVER_IP: 127.0.0.1
      MODE: mini
    ports:
      - "${OCEANBASE_VECTOR_PORT:-2881}:2881"
    healthcheck:
      test: [ 'CMD-SHELL', 'obclient -h127.0.0.1 -P2881 -uroot@test -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"' ]
      interval: 10s
      retries: 30
      start_period: 30s
      timeout: 10s

  # Oracle vector database
  oracle:
    image: container-registry.oracle.com/database/free:latest
    profiles:
      - oracle
    restart: always
    volumes:
      - source: oradata
        type: volume
        target: /opt/oracle/oradata
      - ./startupscripts:/opt/oracle/scripts/startup
    environment:
      ORACLE_PWD: ${ORACLE_PWD:-Dify123456}
      ORACLE_CHARACTERSET: ${ORACLE_CHARACTERSET:-AL32UTF8}

  # Milvus vector database services
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.5
    profiles:
      - milvus
    environment:
      ETCD_AUTO_COMPACTION_MODE: ${ETCD_AUTO_COMPACTION_MODE:-revision}
      ETCD_AUTO_COMPACTION_RETENTION: ${ETCD_AUTO_COMPACTION_RETENTION:-1000}
      ETCD_QUOTA_BACKEND_BYTES: ${ETCD_QUOTA_BACKEND_BYTES:-4294967296}
      ETCD_SNAPSHOT_COUNT: ${ETCD_SNAPSHOT_COUNT:-50000}
    volumes:
      - ./volumes/milvus/etcd:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
    healthcheck:
      test: [ 'CMD', 'etcdctl', 'endpoint', 'health' ]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - milvus

  minio:
    container_name: milvus-minio
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    profiles:
      - milvus
    environment:
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
    volumes:
      - ./volumes/milvus/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"
    healthcheck:
      test: [ 'CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live' ]
      interval: 30s
      timeout: 20s
      retries: 3
    networks:
      - milvus

  milvus-standalone:
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.5.15
    profiles:
      - milvus
    command: [ 'milvus', 'run', 'standalone' ]
    environment:
      ETCD_ENDPOINTS: ${ETCD_ENDPOINTS:-etcd:2379}
      MINIO_ADDRESS: ${MINIO_ADDRESS:-minio:9000}
      common.security.authorizationEnabled: ${MILVUS_AUTHORIZATION_ENABLED:-true}
    volumes:
      - ./volumes/milvus/milvus:/var/lib/milvus
    healthcheck:
      test: [ 'CMD', 'curl', '-f', 'http://localhost:9091/healthz' ]
      interval: 30s
      start_period: 90s
      timeout: 20s
      retries: 3
    depends_on:
      - etcd
      - minio
    ports:
      - 19530:19530
      - 9091:9091
    networks:
      - milvus

  # Opensearch vector database
  opensearch:
    container_name: opensearch
    image: opensearchproject/opensearch:latest
    profiles:
      - opensearch
    environment:
      discovery.type: ${OPENSEARCH_DISCOVERY_TYPE:-single-node}
      bootstrap.memory_lock: ${OPENSEARCH_BOOTSTRAP_MEMORY_LOCK:-true}
      OPENSEARCH_JAVA_OPTS: -Xms${OPENSEARCH_JAVA_OPTS_MIN:-512m} -Xmx${OPENSEARCH_JAVA_OPTS_MAX:-1024m}
      OPENSEARCH_INITIAL_ADMIN_PASSWORD: ${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-Qazwsxedc!@#123}
    ulimits:
      memlock:
        soft: ${OPENSEARCH_MEMLOCK_SOFT:--1}
        hard: ${OPENSEARCH_MEMLOCK_HARD:--1}
      nofile:
        soft: ${OPENSEARCH_NOFILE_SOFT:-65536}
        hard: ${OPENSEARCH_NOFILE_HARD:-65536}
    volumes:
      - ./volumes/opensearch/data:/usr/share/opensearch/data
    networks:
      - opensearch-net

  opensearch-dashboards:
    container_name: opensearch-dashboards
    image: opensearchproject/opensearch-dashboards:latest
    profiles:
      - opensearch
    environment:
      OPENSEARCH_HOSTS: '["https://opensearch:9200"]'
    volumes:
      - ./volumes/opensearch/opensearch_dashboards.yml:/usr/share/opensearch-dashboards/config/opensearch_dashboards.yml
    networks:
      - opensearch-net
    depends_on:
      - opensearch

  # opengauss vector database.
  opengauss:
    image: opengauss/opengauss:7.0.0-RC1
    profiles:
      - opengauss
    privileged: true
    restart: always
    environment:
      GS_USERNAME: ${OPENGAUSS_USER:-postgres}
      GS_PASSWORD: ${OPENGAUSS_PASSWORD:-Dify@123}
      GS_PORT: ${OPENGAUSS_PORT:-6600}
      GS_DB: ${OPENGAUSS_DATABASE:-dify}
    volumes:
      - ./volumes/opengauss/data:/var/lib/opengauss/data
    healthcheck:
      test: [ "CMD-SHELL", "netstat -lntp | grep tcp6 &gt; /dev/null 2&gt;&amp;1" ]
      interval: 10s
      timeout: 10s
      retries: 10
    ports:
      - ${OPENGAUSS_PORT:-6600}:${OPENGAUSS_PORT:-6600}

  # MyScale vector database
  myscale:
    container_name: myscale
    image: myscale/myscaledb:1.6.4
    profiles:
      - myscale
    restart: always
    tty: true
    volumes:
      - ./volumes/myscale/data:/var/lib/clickhouse
      - ./volumes/myscale/log:/var/log/clickhouse-server
      - ./volumes/myscale/config/users.d/custom_users_config.xml:/etc/clickhouse-server/users.d/custom_users_config.xml
    ports:
      - ${MYSCALE_PORT:-8123}:${MYSCALE_PORT:-8123}

  # Matrixone vector store.
  matrixone:
    hostname: matrixone
    image: matrixorigin/matrixone:2.1.1
    profiles:
      - matrixone
    restart: always
    volumes:
      - ./volumes/matrixone/data:/mo-data
    ports:
      - ${MATRIXONE_PORT:-6001}:${MATRIXONE_PORT:-6001}

  # https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html
  # https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-prod-prerequisites
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.14.3
    container_name: elasticsearch
    profiles:
      - elasticsearch
      - elasticsearch-ja
    restart: always
    volumes:
      - ./elasticsearch/docker-entrypoint.sh:/docker-entrypoint-mount.sh
      - dify_es01_data:/usr/share/elasticsearch/data
    environment:
      ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD:-elastic}
      VECTOR_STORE: ${VECTOR_STORE:-}
      cluster.name: dify-es-cluster
      node.name: dify-es0
      discovery.type: single-node
      xpack.license.self_generated.type: basic
      xpack.security.enabled: 'true'
      xpack.security.enrollment.enabled: 'false'
      xpack.security.http.ssl.enabled: 'false'
    ports:
      - ${ELASTICSEARCH_PORT:-9200}:9200
    deploy:
      resources:
        limits:
          memory: 2g
    entrypoint: [ 'sh', '-c', "sh /docker-entrypoint-mount.sh" ]
    healthcheck:
      test: [ 'CMD', 'curl', '-s', 'http://localhost:9200/_cluster/health?pretty' ]
      interval: 30s
      timeout: 10s
      retries: 50

  # https://www.elastic.co/guide/en/kibana/current/docker.html
  # https://www.elastic.co/guide/en/kibana/current/settings.html
  kibana:
    image: docker.elastic.co/kibana/kibana:8.14.3
    container_name: kibana
    profiles:
      - elasticsearch
    depends_on:
      - elasticsearch
    restart: always
    environment:
      XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: d1a66dfd-c4d3-4a0a-8290-2abcb83ab3aa
      NO_PROXY: localhost,127.0.0.1,elasticsearch,kibana
      XPACK_SECURITY_ENABLED: 'true'
      XPACK_SECURITY_ENROLLMENT_ENABLED: 'false'
      XPACK_SECURITY_HTTP_SSL_ENABLED: 'false'
      XPACK_FLEET_ISAIRGAPPED: 'true'
      I18N_LOCALE: zh-CN
      SERVER_PORT: '5601'
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    ports:
      - ${KIBANA_PORT:-5601}:5601
    healthcheck:
      test: [ 'CMD-SHELL', 'curl -s http://localhost:5601 &gt;/dev/null || exit 1' ]
      interval: 30s
      timeout: 10s
      retries: 3

  # unstructured .
  # (if used, you need to set ETL_TYPE to Unstructured in the api &amp; worker service.)
  unstructured:
    image: downloads.unstructured.io/unstructured-io/unstructured-api:latest
    profiles:
      - unstructured
    restart: always
    volumes:
      - ./volumes/unstructured:/app/data

networks:
  # create a network between sandbox, api and ssrf_proxy, and can not access outside.
  ssrf_proxy_network:
    driver: bridge
    internal: true
  milvus:
    driver: bridge
  opensearch-net:
    driver: bridge
    internal: true

volumes:
  oradata:
  dify_es01_data:
</code></pre>
<p>其实一个一个分析，它的结构和我们之前部署的docker项目是类似的，只不过一次性起了很多个容器。</p>
<p>我们这边可以先不管它，直接暴力拉起</p>
<pre><code class="language-bash">docker compose up -d
</code></pre>
<p>我这边在公司，本来以为很快能拉好镜像，结果网非常的慢，我等不及就去吃中饭了，等到吃饭回来发现已经拉好了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160453-1.webp&amp;size=m" alt="img"></p>
<p>在这期间，如果决定要本地使用，不调用云端API的话，我们可以先把Ollama和本地的模型先下载起来。</p>
<h2 id="安装Ollama-可选-">安装Ollama（可选）</h2>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160447-1.webp&amp;size=m" alt="img"></p>
<p>其实这个也可以用docker来装，但是既然给了安装版，我们就直接到官网下载即可。</p>
<p>什么是Ollama？</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F05%2F21%2F110652-1.webp&amp;size=m" alt="62dc7ef085dd48a06b4bcce9782a12c5.png" style="zoom:33%;">
<p>Ollama 是一个便于本地部署和运行大型语言模型（Large Language Models, LLMs）的工具。使用通俗的语言来说，如果你想在自己的电脑上运行如 GPT这样的大型人工智能模型，而不是通过互联网连接到它们，那么 Ollama 是一个实现这一目标的工具。</p>
<p>Ollama支持非常多的开源模型，比如：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160440-1.webp&amp;size=m" alt="img"></p>
<p>更多支持的模型可以看这边：https://ollama.com/library</p>
<p>当然它还支持自定义模型，这边就不深入了，有兴趣的可以研究：https://github.com/ollama/ollama</p>
<p>装好之后，命令行运行:</p>
<pre><code class="language-bash">ollama -v
</code></pre>
<p>查看到版本号说明安装好了。</p>
<p>接下来，比如我们下载一个llama3 8B的模型：</p>
<pre><code class="language-bash">ollama run llama3
</code></pre>
<p>这边可能需要比较长的时间，取决于你的网速。</p>
<p>下载好了就可以进行交互了：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160436-1.webp&amp;size=m" alt="b8179cebba4cd58465fd233020035fc9.png"></p>
<p><code>/?</code> 可以查看帮助：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160434-1.webp&amp;size=m" alt="576b3e8c12d6561d8c9059e8b8504d14.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160430-1.webp&amp;size=m" alt="7a9e6a8e285b4562c6a39c83a0c468b5.png"></p>
<p><code>/bye</code> 可以退出</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160428-1.webp&amp;size=m" alt="f6b660f17b96db1219cff57b888ec428.png" style="zoom:50%;">
<p>其实现在已经搞定了，你可以让它帮你干活了，但是每次都要用命令行，有些人觉得不方便，而且也不能给别人用，下面我们就给它搞一个图形化界面，扩展一下功能，也能让局域网里的其他小伙伴也用上你的这个模型（注意多人同时访问会导致机器负载飙升，具体取决于你机器的性能和模型参数的大小）</p>
<h2 id="配置Dify">配置Dify</h2>
<p>等所有容器都拉取好了，我们就可以通过在浏览器地址栏输入:<code>127.0.0.1</code>来访问Dify了。</p>
<p>第一次登录会让你注册一个管理员账号，然后我们就可以登录了，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160422-1.webp&amp;size=m" alt="img"></p>
<p>后台是这个样子的，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160420-1.webp&amp;size=m" alt="img"></p>
<p>我们先来到设置，配置一下大模型，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160417-1.webp&amp;size=m" alt="f0ba80de97e161c2021d2cebc76c1306.png"></p>
<p>这边可以看到很多的模型供应商，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160412-1.webp&amp;size=m" alt="img"></p>
<p>我们本地部署，就用ollama，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160409-1.webp&amp;size=m" alt="img"></p>
<p>点击安装，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160407-1.webp&amp;size=m" alt="img"></p>
<p>安装好了之后，来添加模型，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160405-1.webp&amp;size=m" alt="img"></p>
<p>这里的基础URL，填写：<code>http://host.docker.internal:11434</code></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160402-1.webp&amp;size=m" alt="img"></p>
<p>模型名称的话，看看我们ollama里下载了什么模型，打开终端，输入</p>
<pre><code class="language-bash">ollama list
</code></pre>
<p>可以看到我这边下载了很多模型，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160359-1.webp&amp;size=m" alt="img"></p>
<p>我们就选择gpt最近刚开源的<code>gpt-oss:20b</code></p>
<p>其他信息填写如图，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160355-1.webp&amp;size=m" alt="632a2fed26d697929b7faa2867d9895b.png"></p>
<p>这边是支持函数调用的，选择是，不支持视觉，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160350-1.webp&amp;size=m" alt="81e6c15393c9cfc5032318734b6b51e4.png"></p>
<p>这样我们就添加好一个模型啦。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160337-1.webp&amp;size=m" alt="img"></p>
<p>如果你的本地电脑算力不够，也可以选择使用云端的模型，比如DeepSeek之类的，</p>
<p>添加方法也很简单，下载模型供应商，然后在这边点击配置，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160335-1.webp&amp;size=m" alt="img"></p>
<p>填入你在DeepSeek官网拿到的API Key就行了。</p>
<p>OpenAI、ANTHROPIC也是类似的方法，填API Key就可以。</p>
<p>接着，我们就来创建一个空白应用，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160332-1.webp&amp;size=m" alt="img"></p>
<p>这边选择最简单的，创建一个聊天助手，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160331-1.webp&amp;size=m" alt="img"></p>
<p>创建的过程中，你可以调试，这边的自定义程度会高一些，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160327-1.webp&amp;size=m" alt="img"></p>
<p>创建好之后，可以选择发布，或者点击探索，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F28%2F160319-1.webp&amp;size=m" alt="img"></p>
<p>就可以在这边调出使用了。</p>
<p>当然，这只是最简单的功能，dify的魅力在于<strong>降低AI应用开发的门槛，快速构建和部署生产级的生成式AI应用</strong></p>
<p>它通过以下核心功能来实现这个目标：</p>
<ol>
 <li><strong>简化开发流程</strong>：Dify是一个开源的大语言模型（LLM）应用开发平台，融合了后端即服务（BaaS）和LLMOps理念，提供可视化的Prompt编排、数据集管理、RAG（检索增强生成）引擎、Agent框架等功能，使开发者无需深入底层技术也能快速搭建AI应用。</li>
 <li><strong>支持低代码/无代码开发</strong>：通过直观的界面和拖拽操作，非技术人员也能参与AI应用的定义和数据运营，极大地降低了开发门槛。</li>
 <li><strong>灵活的模型支持</strong>：Dify支持多种主流大语言模型（如GPT、Claude、DeepSeek等）以及开源模型，开发者可根据需求灵活选择和切换模型。</li>
 <li><strong>高效的RAG和Agent功能</strong>：Dify的RAG技术通过结合外部知识库提升生成内容的准确性，而Agent框架赋予AI自主推理和任务执行能力，适用于复杂场景如智能客服、内容生成等。189.html)</li>
 <li><strong>企业级应用支持</strong>：Dify提供私有化部署、API集成、多租户隔离等功能，适合企业构建内部AI网关或快速将AI能力融入现有业务，助力AI转型。</li>
</ol>
<p>总结来说，Dify通过提供一站式、易用的开发平台，帮助开发者、企业甚至非技术人员快速实现AI应用创意，节省开发时间，专注于创新和业务需求，特别适合从原型设计到生产部署的全流程管理。</p>
<p>大家可以自行探索一下Dify的高级玩法，我自己也在慢慢摸索学习，之后有机会可以和大家分享！</p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-dify</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Thu, 28 Aug 2025 08:50:27 GMT</pubDate></item><item><title><![CDATA[支持MCP，轻量又全面的记账软件——ezBookkeeping｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-ezbookkeeping</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E6%94%AF%E6%8C%81MCP%EF%BC%8C%E8%BD%BB%E9%87%8F%E5%8F%88%E5%85%A8%E9%9D%A2%E7%9A%84%E8%AE%B0%E8%B4%A6%E8%BD%AF%E4%BB%B6%E2%80%94%E2%80%94ezBookkeeping%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-ezbookkeeping" width="1" height="1" alt="" style="opacity:0;">
<p>前阵子去欧洲玩了一段时间，鸽了挺久了，今天有点时间，立马来和大家分享好玩儿的Docker项目。</p>
<h2 id="1--介绍">1. 介绍</h2>
<p>ezBookkeeping 是一款轻量级的个人理财应用，你可以自己架设（自托管）。它界面简洁，用起来很顺手，记账功能也强大。</p>
<p>这款应用的设计核心就是<strong>简单</strong>和<strong>便携</strong>。它部署起来毫不费力，上手快，而且对系统资源的占用极小。无论是微型服务器、NAS 设备，还是树莓派，都能轻松运行。</p>
<p>ezBookkeeping 支持全平台，对各种设备都很友好。在手机、平板和电脑上用，体验都一样流畅。它还支持 PWA（渐进式网页应用），你可以直接把它添加到手机主屏幕，像本地应用一样方便地使用。</p>
<h3 id="1-1-功能特点">1.1 功能特点</h3>
<p><strong>开源与自托管</strong></p>
<ul>
 <li>为你提供隐私和数据控制权</li>
</ul>
<p><strong>轻量又快速</strong></p>
<ul>
 <li>性能卓越，即使在低配置环境下也能流畅运行</li>
</ul>
<p><strong>安装简单</strong></p>
<ul>
 <li>支持 Docker 部署</li>
 <li>兼容 SQLite, MySQL, PostgreSQL 数据库</li>
 <li>跨平台运行（支持 Windows, macOS, Linux）</li>
 <li>支持多种处理器架构 (x86, amd64, ARM)</li>
</ul>
<p><strong>界面友好</strong></p>
<ul>
 <li>界面已针对移动和桌面设备优化</li>
 <li>支持 PWA，在手机上可获得类似原生应用的体验</li>
 <li>提供深色模式</li>
</ul>
<p><strong>AI 赋能</strong></p>
<ul>
 <li>支持 MCP (Model Context Protocol)，可集成 AI 功能</li>
</ul>
<p><strong>强大的记账功能</strong></p>
<ul>
 <li>支持两级账户和分类</li>
 <li>可为交易添加图片附件</li>
 <li>具备地图位置追踪功能</li>
 <li>支持周期性（重复）交易</li>
 <li>提供高级筛选、搜索、数据可视化和分析功能</li>
</ul>
<p><strong>本地化与全球化</strong></p>
<ul>
 <li>支持多种语言和货币</li>
 <li>自动更新汇率</li>
 <li>支持多时区显示</li>
 <li>可自定义日期、数字和货币格式</li>
</ul>
<p><strong>安全保障</strong></p>
<ul>
 <li>支持双重身份验证 (2FA)</li>
 <li>登录频率限制</li>
 <li>应用锁定功能（支持 PIN 码 / WebAuthn）</li>
</ul>
<p><strong>数据导入/导出</strong></p>
<ul>
 <li>支持多种格式，包括 CSV, OFX, QFX, QIF, IIF, Camt.053, MT940, GnuCash, Firefly III, Beancount 等等</li>
</ul>
<p>简单来说，这是一个记账的项目，然后它还可以支持MCP，可以搭配大语言模型一起食用。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F203854-1.webp&amp;size=m" alt="fa0b25dbc1ebb8c3e364c5de96542aff.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F203856-1.webp&amp;size=m" alt="6cd6cae5e006175532d59840d5683924.png"></p>
<h2 id="2--相关地址">2. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/mayswind/ezbookkeeping">https://github.com/mayswind/ezbookkeeping</a> (目前958个star，欢迎大家去给作者点星星！）</p>
<p>官方Demo：<a href="https://ezbookkeeping-demo.mayswind.net">https://ezbookkeeping-demo.mayswind.net</a></p>
<h2 id="3--搭建环境">3. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的是<a href="https://gao.ee/lca">莱卡云香港服务器</a>，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。内存1G以上即可，硬盘当然是越大越好啦。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="4--搭建视频-有时间补充--">4. 搭建视频（有时间补充！）</h2>
<h3 id="4-1-YouTube">4.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="4-2-哔哩哔哩">4.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="5--搭建方式">5. 搭建方式</h2>
<h3 id="5-1-安装-Docker-与-Nginx-Proxy-Manager">5.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="5-2-创建安装目录">5.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/ezbookkeeping

cd ezbookkeeping
</code></pre>
<p>我们来简单修改一下作者提供的<code>docker-compose.yml</code>文件</p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<p>咕咕修改之后的：</p>
<pre><code class="language-yaml">services:
  ezbookkeeping:
    image: mayswind/ezbookkeeping
    container_name: ezbookkeeping
    restart: unless-stopped
    ports:
      - 8082:8080
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./storage:/ezbookkeeping/storage
      - ./log:/ezbookkeeping/log
    #  - ./ezbookkeeping.ini:/ezbookkeeping/conf/ezbookkeeping.ini
    environment:
      - EBK_DATABASE_TYPE=mysql
      - EBK_DATABASE_HOST=mysql:3306
      - EBK_DATABASE_NAME=ezbookkeeping
      - EBK_DATABASE_USER=ezbookkeeping
      - EBK_DATABASE_PASSWD=ezbookkeeping
      - EBK_LOG_MODE=file
      - EBK_SECURITY_SECRET_KEY=its_should_be_a_random_string
      - EBK_MCP_ENABLE_MCP=true
    # depends_on:
    #  mysql:
    #    condition: service_healthy

  mysql:  
    image: mysql:8.0 
    container_name: ezbookkeeping-mysql
    restart: unless-stopped
    volumes:  
        - ./data:/var/lib/mysql
    environment:  
        - MYSQL_DATABASE=ezbookkeeping  
        - MYSQL_USER=ezbookkeeping  
        - MYSQL_PASSWORD=ezbookkeeping  
        - MYSQL_ROOT_PASSWORD=ezbookkeeping
    healthcheck:  
        test: ["CMD", "mysqladmin", "ping", "-p ezbookkeeping"]  
        retries: 3  
        timeout: 5s
</code></pre>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<p>接着创建文件夹，赋予文件权限：</p>
<pre><code class="language-bash">cd /root/data/docker_data/ezbookkeeping
mkdir ./{data,log,storage}
chmod a+rw {log,storage}
</code></pre>
<h3 id="5-3-打开服务器防火墙-非必需-并访问网页">5.3 打开服务器防火墙（非必需）并访问网页</h3>
<p>打开防火墙的端口 <code>8082</code></p>
<p>举例，腾讯云打开方法如下（部分服务商没有自带的面板防火墙，就不用这步操作了）：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F06%2F30%2Fzlio5h-2.webp&amp;size=m" alt="image-20220630215240864" style="zoom: 25%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F06%2F30%2F10h3dqt-2.webp&amp;size=m" alt="image-20220630220546335" style="zoom: 25%;">
<p>类似图中的，这边我们填 <code>8082</code>，示例填 <code>ezbookkeeping</code> ，确定即可（如果你在 docker-compose 文件里换了 <code>9009</code>，这边就需要填 <code>9009</code>，以此类推）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093305-1.webp&amp;size=m" alt="56a42aff23098af08c1ae587e19739ae.png" style="zoom:33%;">
<p>查看端口是否被占用（以 <code>8082</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:8082  #查看 8082 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="5-4-启动-ezbookkeeping">5.4 启动 ezbookkeeping</h3>
<pre><code>cd /root/data/docker_data/ezbookkeeping

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:8082</code> 访问了。</p>
<p>但是这边我们推荐先搞一下反向代理！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="6--反向代理">6. 反向代理</h2>
<h3 id="6-1-利用-Nginx-Proxy-Manager">6.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093302-1.webp&amp;size=m" alt="4b00cb7fe121c71233685dcc787fdf32.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201955-1.webp&amp;size=m" alt="9a07c1b059cf95aae62081a18f2ad5d8.png" style="zoom:33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201945-1.webp&amp;size=m" alt="c1fa9d7b7a32927f020093975c6fd8ea.png" style="zoom:33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201941-1.webp&amp;size=m" alt="396509498ad5fd92b67f6a782cade133.png" style="zoom:33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201935-1.webp&amp;size=m" alt="e5362e20c7d6d271d1e8103b0511ac04.png" style="zoom:33%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>8082</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 ezbookkeeping 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F09%2F29%2Fpcdnz5-2.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 <strong>ezbookkeeping 所在的服务器 IP</strong> 就行。</p>
<h3 id="6-2-利用宝塔面板">6.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201927-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F08%2F19%2Fowbbkb-2.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:8082/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093233-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="7--使用教程">7. 使用教程</h2>
<p>登录你的域名之后，可以看到首页：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201919-1.webp&amp;size=m" alt="7a03c1ab0e2dd10aa34612cba853e3ed.png"></p>
<p>这个时候需要创建一个新账号：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201916-1.webp&amp;size=m" alt="826b774725884ccd0ba5d7bb5758c241.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201914-1.webp&amp;size=m" alt="39679f5841b71f65fb9f2133518e24c5.png"></p>
<p>这里的预设分类，可以选择打开：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201911-1.webp&amp;size=m" alt="5f1aacee44cf4f3e03d077634743e047.png"></p>
<p>进入后台，结构很清晰：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201909-1.webp&amp;size=m" alt="694dcf2d58bfaadaa204d13269549e9d.png"></p>
<p>我们先来添加一下账户：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201907-1.webp&amp;size=m" alt="3cefdb5bf5493e24f16be3df8c491cfe.png"></p>
<p>比如，取名就叫做“咕咕的账本”：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201904-1.webp&amp;size=m" alt="b9869d80991a30d1f4e46bf18999a778.png" style="zoom:50%;">
<p>先来手动添加一笔试试看：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201859-1.webp&amp;size=m" alt="f3b17b3c3f41f5eb0e4f5521bbf1d214.png"></p>
<p>可以正常添加：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201857-1.webp&amp;size=m" alt="e9f717d2e4a0fd9ef38bb95eb89a79bb.png"></p>
<h3 id="MCP配置">MCP配置</h3>
<p>一开始我们就说了，这个账本支持MCP。</p>
<p>MCP（模型上下文协议）是由 Anthropic 开发的一种开放协议，它能让 AI 模型安全地连接到外部数据源和和工具。</p>
<p>简单来说，MCP 就像一座桥梁，它提供了一种通用的标准，让 AI 工具能安全地获取信息和执行操作，同时确保数据安全和用户可以掌控一切。</p>
<p>有了 MCP 协议，你就可以用自己喜欢的 AI 工具来：</p>
<ul>
 <li><strong>添加交易记录</strong>：比如，直接用自然语言（就是日常说话的方式）来创建交易，或者从不同的文件格式中批量导入交易记录。</li>
 <li><strong>查询交易数据</strong>：比如，让你的 AI 工具帮你分析历史交易记录。</li>
 <li><strong>以及做更多的事情</strong>。</li>
</ul>
<p>更多MCP相关介绍可以看这边：https://ezbookkeeping.mayswind.net/mcp</p>
<p>这边我们来看看怎么配置。</p>
<p>首先找到右上角的用户设置，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201854-1.webp&amp;size=m" alt="e66ee48541f398f0c84c40b839e68388.png" style="zoom:33%;">
<p>生成MCP令牌：</p>
<p>有两种形式，分别是普通的令牌和json配置：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201850-1.webp&amp;size=m" alt="7bcc4a9580e9e7d3c1fa1a74d0401b90.png"></p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201848-1.webp&amp;size=m" alt="ab7a8343aff185cf6ab7475b925f0ea4.png" style="zoom:50%;">
<p>普通：</p>
<pre><code class="language-bash">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyVG9rZW5JZCI6IjMzOTQ1NTM3NTIyOTE5OTc4MzYiLCJqdGkiOiIzNzY4ODA2Njg4MjQ1NjbWUiOiJSb3kiLCJ0eXBlIjo1LCJpYXQiOjE3NTQ5ODc3NzcsImV4cCI6MTA5NzgzNTk4MTR9.7JL_4kzKhihatpfQxIkhD6Z_ibZ_vBYtcQ_D9UCV--0
</code></pre>
<p>JSON配置：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201843-1.webp&amp;size=m" alt="c5dfb5b8dfc24e1ca0e2303fece2cde2.png" style="zoom:50%;">
<pre><code class="language-json">{
    "mcpServers": {
        "ezbookkeeping-mcp": {
            "type": "streamable-http",
            "url": "http://localhost:8080/mcp",
            "headers": {
                "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyVG9rZW5JZCI6IjMzOTQ1NTM3NTIyOTE5OTc4MzYiLCJqdGkiOiIzNzY4ODA2Njg4hbWUiOiJSb3kiLCJ0eXBlIjo1LCJpYXQiOjE3NTQ5ODc3NzcsImV4cCI6MTA5NzgzNTk4MTR9.7JL_4kzKhihatpfQxIkhD6Z_ibZ_vBYtcQ_D9UCV--0"
            }
        }
    }
}
</code></pre>
<p>这边可以保存下来，下次打开就看不到了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201836-1.webp&amp;size=m" alt="29a8936f32b3247acb4510626a85c87b.png"></p>
<h3 id="Cherry-Studio配置">Cherry Studio配置</h3>
<p>这边以Cherry Studio为例，看看MCP怎么配置。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201834-1.webp&amp;size=m" alt="706dbf1ee98c6368863418e1a638da1c.png"></p>
<p>配置情况如图：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201831-1.webp&amp;size=m" alt="57f3580946e4072cba358958444ff08f.png"></p>
<ul>
 <li><code>名称</code>：主要用于识别，例如：<code>ezBookkeeping</code></li>
 <li><code>类型</code>：选择 <code>streamableHttp</code> 协议</li>
 <li><code>URL</code>：为 <code>你的域名/mcp</code></li>
 <li><code>请求头</code>： 为 <code>Authorization=Bearer {token}</code></li>
</ul>
<p>接着可以查看一下可以调用的工具：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201829-1.webp&amp;size=m" alt="c24978aa0964d06246f059399f92ee88.png"></p>
<p>然后为了确保大模型能正确理解什么是今天，还需要加个时间MCP，这次我们选择json导入，</p>
<pre><code class="language-json">{
    "mcpServers": {
        "mcp-server-time": {
            "command": "uvx",
            "args": ["mcp-server-time"]
        }
    }
}
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201826-1.webp&amp;size=m" alt="3a3ab3900b6dba588cbcdf54b8f47245.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201824-1.webp&amp;size=m" alt="ca6653fe3ec6dfe069da60592b40b369.png"></p>
<p>这下，你应该有两个MCP服务了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201822-1.webp&amp;size=m" alt="8b12dc8711e6936375bb1d880271102a.png"></p>
<p>查看一下时间工具的功能：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201820-1.webp&amp;size=m" alt="369abc91ad148e042f9e796c8580312e.png"></p>
<p>接着，我们到Cherry Studio里新建一个助手，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201817-1.webp&amp;size=m" alt="399ab6071f945797e0fb61349d00cd16.png"></p>
<p>选择启用这两个MCP服务：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201816-1.webp&amp;size=m" alt="4775185163eb58be74204ea756d6b915.png"></p>
<p>测试一下，可以看到回答的时候，调用了MCP服务，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201813-1.webp&amp;size=m" alt="b65c160f578c98b0f083b0add6a749bb.png"></p>
<p>这边提示错误，我没有说记录到哪个账本：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201810-1.webp&amp;size=m" alt="4f1fc419fafb5fc9f55764aca9b20b5d.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201809-1.webp&amp;size=m" alt="900832a98c968a38f541aff971a5b140.png"></p>
<p>还需要说明交易类别，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201807-1.webp&amp;size=m" alt="6cc43ba6b7f0df94f756c836bc1b5de4.png"></p>
<p>后续，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201805-1.webp&amp;size=m" alt="fca2836dc485e298003061c20dd71ec3.png"></p>
<p>记录成功！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201802-1.webp&amp;size=m" alt="756e050ca91dfb4f2a1f5b3020baa75c.png"></p>
<p>不过这次似乎没有调用时间MCP，时间似乎有问题……</p>
<p>然后我尝试使用Deepseek，直接不调用MCP服务了，很奇怪。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F201756-1.webp&amp;size=m" alt="8c18d8491e297ce50cc941024a31a3c2.png"></p>
<p>后续一直没调用MCP服务，暂时还没解决，我的是Mac，有解决的小伙伴可以评论区分享一下。</p>
<h3 id="7-1-更新-ezbookkeeping">7.1 更新 ezbookkeeping</h3>
<pre><code class="language-bash">cd /root/data/docker_data/ezbookkeeping

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="7-2-卸载-ezbookkeeping">7.2 卸载 ezbookkeeping</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/ezbookkeeping

docker compose down

cd ..

rm -rf /root/data/docker_data/ezbookkeeping  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="8--常见问题及注意点">8. 常见问题及注意点</h2>
<p>还是MCP调用的问题，不是非常稳定，暂时不确定是不是Cherry Studio的问题。</p>
<h2 id="9--结尾">9. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/mayswind/ezbookkeeping/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，项目处于初期，有能力给项目做贡献的同学，也欢迎积极加入到 [项目]https://github.com/mayswind/ezbookkeeping) 中来，贡献自己的一份力量！</p>
<p>最后，感谢开发人员们的辛苦付出，让我们能用到这么优秀的项目！也希望开源项目越来越好！</p>
<h2 id="10--参考资料">10. 参考资料</h2>
<p>官方GitHub：<a href="https://github.com/mayswind/ezbookkeeping">https://github.com/mayswind/ezbookkeeping</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-ezbookkeeping</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F08%2F12%2F202856-1.webp&amp;size=m" type="image/jpeg" length="34392"/><category>Docker系列</category><pubDate>Tue, 12 Aug 2025 12:36:51 GMT</pubDate></item><item><title><![CDATA[拒绝恶意收购，十分钟搭建AList的替代品——OpenList｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-openlist</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E6%8B%92%E7%BB%9D%E6%81%B6%E6%84%8F%E6%94%B6%E8%B4%AD%EF%BC%8C%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BAAList%E7%9A%84%E6%9B%BF%E4%BB%A3%E5%93%81%E2%80%94%E2%80%94OpenList%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-openlist" width="1" height="1" alt="" style="opacity:0;">
<p>最近事情比较多，鸽了好一阵子了。前阵子Alist被收购的事情，相信不少小伙伴可能已经有了解。</p>
<p>这边给还不清楚的小伙伴简单梳理一下。</p>
<h2 id="1--介绍">1. 介绍</h2>
<p>AList是一个广受欢迎的开源项目，支持多种云存储的统一管理和WebDAV功能，因其便捷性和强大的网盘聚合能力在开发者社区中积累了近5万星标。</p>
<p>咕咕在自己的博客里也介绍过这个项目——<a href="https://blog.laoda.de/archives/docker-install-alist">【好玩的Docker项目】目前最好用的网盘直链程序——AList，支持市面上几乎所有网盘！可以代替Olaindex！</a> (突然发现已经是三年前的事情了 = =)</p>
<p>然而，2025年6月爆出的项目被出售事件引发了开源社区的激烈反响。</p>
<h3 id="事件背景">事件背景</h3>
<ul>
 <li><strong>项目出售</strong>：据多方消息，AList被原开发者Xhofe出售给贵州不够科技有限公司（BugoTech），交易过程未公开，缺乏社区通知。原开发者确认项目已交由公司运营，自己仅保留代码审查权，main分支启用PR审核和CI自动构建以确保透明性。</li>
 <li><strong>争议操作</strong>：新维护者（账号alist666）提交的PR #8633被发现包含收集用户设备信息并上传至私有服务器的代码，引发“供应链投毒”担忧，虽因社区压力撤回，但信任危机加剧。文档被大幅修改，移除原作者信息，新增商业化内容（如VIP技术支持和QQ群），官网域名从alist.nn.ci更换为alistgo.com，旧链接404。</li>
 <li><strong>收购方背景</strong>：不够科技此前收购Hutool、LNMP等项目，伴随权限争议和疑似“投毒”历史，社区对其声誉存疑。</li>
</ul>
<h3 id="社区反应">社区反应</h3>
<ol>
 <li>
  <p><strong>愤怒与失望</strong>：</p>
  <ul>
   <li><strong>信任崩塌</strong>：社区对原开发者Xhofe未提前公告的“暗箱操作”表示强烈不满，认为此举背叛了开源精神，伤害了用户和贡献者的信任。GitHub Issues区被大量批评淹没，新维护者删除质疑帖并移除反对者进一步激化矛盾。</li>
   <li><strong>隐私担忧</strong>：AList涉及网盘Token和Cookie等敏感数据，用户担心新版本可能泄露隐私或被植入恶意代码。社区建议锁定v3.40.0版本，解除网盘授权，并备份重要文件。</li>
   <li><strong>对收购方的质疑</strong>：不够科技的“黑历史”被广泛讨论，社区将其与此前LNMP、Oneinstack的闭源和投毒争议联系起来，称其为“傻逼公司”“bug科技”，对其动机和代码安全性高度警惕。</li>
  </ul>
 </li>
 <li>
  <p><strong>社区自救与分叉</strong>：</p>
  <ul>
   <li><strong>分叉项目</strong>：开发者迅速行动，创建了OpenList等分叉项目，移除不可信代码并审计近半年提交，短时间内获数千星标，显示社区对替代方案的热情。</li>
   <li><strong>替代方案</strong>：技术博客推荐Zdir、Cloudreve等私有网盘程序，鼓励用户迁移以规避风险。</li>
   <li><strong>安全建议</strong>：社区提出锁定版本、校验哈希、隔离网络、自行编译等措施，强调去中心化分发和社区监督的重要性。</li>
  </ul>
 </li>
 <li>
  <p><strong>对原开发者的复杂情绪</strong>：</p>
  <ul>
   <li><strong>理解与支持</strong>：部分开发者（如@DIYgod）表示理解Xhofe的决定，认为开源维护的长期孤独和无回报让变现成为合理选择，祝福其获得回报。贡献图显示Xhofe个人提交超90%代码，凸显其付出。</li>
   <li><strong>批评与指责</strong>：更多用户认为Xhofe将社区贡献和用户数据“卖给有前科的公司”是不道德的，称其“把用户当交易品”，损害了开源生态的信任。</li>
  </ul>
 </li>
</ol>
<h3 id="评价">评价</h3>
<ul>
 <li><strong>对原开发者的行为</strong>：Xhofe作为主要贡献者有权在MIT/AGPL-3.0许可证框架内转让项目，但未公开透明的做法违背了开源社区的信任契约。 虽然其后续承诺代码审查，但“悄然退出”和“配合移除贡献者痕迹”让社区感到被背叛，凸显了单一开发者主导项目的风险。</li>
 <li><strong>对收购方的操作</strong>：不够科技的历史记录和新代码的隐私收集行为引发合理担忧，其商业化导向（如VIP服务）与开源精神冲突。删除批评和接管仓库的“粗暴”操作进一步破坏信任，可能导致AList用户流失。</li>
 <li><strong>社区的应对</strong>：社区的激烈反应反映了对开源项目透明度和数据安全的重视。分叉项目和替代方案的迅速涌现展现了开源生态的韧性，但也暴露了国内开源项目变现难、社区监督机制不足的问题。</li>
 <li><strong>对开源生态的启示</strong>：AList事件敲响警钟，提醒用户关注项目维护的可持续性和开发者的稳定性。建议建立贡献者许可协议（CLA）和社区监督机制，防止类似“野蛮收购”。用户应谨慎选择涉及敏感数据的开源工具，优先考虑社区主导的项目。</li>
</ul>
<h3 id="结论">结论</h3>
<p>AList被收购事件引发了开源社区的信任危机，社区的愤怒源于对隐私安全和开源精神的双重担忧。尽管部分人理解原开发者的变现动机，但其隐秘操作和收购方的争议历史让事件成为“开源之耻”。社区通过分叉和替代方案展现了自救能力，但事件也暴露了国内开源生态在商业化与信任之间的矛盾。用户应保持警惕，优先选择透明、社区驱动的项目，同时推动更完善的开源治理机制。</p>
<p>这一期，我们就来分享一个Alist的开源替代——OpenList。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093316-1.webp&amp;size=m" alt="ecd1fc88db4311c5f021b48eea89155e.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093313-1.webp&amp;size=m" alt="b052fa406d61edce52e385f01a60fddf.png"></p>
<blockquote>
 <p>如果你之前安装过 Alist，其实只要在<code>docker-compose.yml</code>修改两处：</p>
 <ul>
  <li>镜像名从 <code>xhofe/alist</code> 改为 <code>openlistteam/openlist</code></li>
  <li>映射的容器内的路径，由 <code>/opt/alist/</code> 改为 <code>/opt/openlist/</code>（如果添加了本地存储，记得也修改一下根文件夹路径，其他网盘不影响）</li>
 </ul>
 <p>运行之前，最好对原来的数据进行一次备份，运行之后，原来怎么使用，现在还是一样的。</p>
</blockquote>
<h2 id="2--相关地址">2. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/OpenListTeam/OpenList">https://github.com/OpenListTeam/OpenList</a> (目前10.6k个star，欢迎大家去给作者点星星！）</p>
<h2 id="3--搭建环境">3. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的是OVH的杜甫，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。内存1G以上即可，硬盘当然是越大越好啦。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="4--搭建视频-有时间补充--">4. 搭建视频（有时间补充！）</h2>
<h3 id="4-1-YouTube">4.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="4-2-哔哩哔哩">4.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="5--搭建方式">5. 搭建方式</h2>
<h3 id="5-1-安装-Docker-与-Nginx-Proxy-Manager">5.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="5-2-创建安装目录">5.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/openlist

cd openlist
</code></pre>
<p>我们来简单修改一下作者提供的<code>docker-compose.yml</code>文件</p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<p>咕咕修改之后的（其实就是修改了端口号和删除了<code>version: "3.7"</code>）：</p>
<pre><code class="language-yaml">services:
  openlist:
    image: 'openlistteam/openlist:latest'
    container_name: openlist
    volumes:
      - '/data:/opt/openlist/data'
      - './share:/opt/openlist/share'
    ports:
      - '5288:5244'
    environment:
      - PUID=0
      - PGID=0
      - UMASK=022
    restart: unless-stopped
</code></pre>
<p>修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="5-3-打开服务器防火墙-非必需-并访问网页">5.3 打开服务器防火墙（非必需）并访问网页</h3>
<p>打开防火墙的端口 <code>5288</code></p>
<p>举例，腾讯云打开方法如下（部分服务商没有自带的面板防火墙，就不用这步操作了）：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F06%2F30%2Fzlio5h-2.webp&amp;size=m" alt="image-20220630215240864" style="zoom: 25%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F06%2F30%2F10h3dqt-2.webp&amp;size=m" alt="image-20220630220546335" style="zoom: 25%;">
<p>类似图中的，这边我们填 <code>5288</code>，示例填 <code>openlist</code> ，确定即可（如果你在 docker-compose 文件里换了 <code>9009</code>，这边就需要填 <code>9009</code>，以此类推）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093305-1.webp&amp;size=m" alt="56a42aff23098af08c1ae587e19739ae.png" style="zoom:33%;">
<p>查看端口是否被占用（以 <code>5288</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:5288  #查看 5288 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="5-4-启动-openlist">5.4 启动 openlist</h3>
<pre><code>cd /root/data/docker_data/openlist

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:5288</code> 访问了。</p>
<p>但是这边我们推荐先搞一下反向代理！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="6--反向代理">6. 反向代理</h2>
<h3 id="6-1-利用-Nginx-Proxy-Manager">6.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093302-1.webp&amp;size=m" alt="4b00cb7fe121c71233685dcc787fdf32.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093259-1.webp&amp;size=m" alt="1a1ff8255bb0ae59f7dcb9b492fa3f11.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093253-1.webp&amp;size=m" alt="e412c3244963f658bd1521eca54de921.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093249-1.webp&amp;size=m" alt="3f2b568516e72dab959680f84f40a83e.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093245-1.webp&amp;size=m" alt="3c9ea7731f53d6e51b7cf6cbe1c3c532.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>5288</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 openlist 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F09%2F29%2Fpcdnz5-2.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 <strong>openlist 所在的服务器 IP</strong> 就行。</p>
<h3 id="6-2-利用宝塔面板">6.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F08%2F19%2Fov4xrt-2.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2022%2F08%2F19%2Fowbbkb-2.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:5288/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093233-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="7--使用教程">7. 使用教程</h2>
<p>首先来输入命令：</p>
<pre><code class="language-bash">docker compose logs
</code></pre>
<p>查看一下初始的登录密码：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093229-1.webp&amp;size=m" alt="3813385afd8b3e7c33c374f95c642d7b.png"></p>
<p>这边的密码是<code>OVoPTw5B</code></p>
<p>打开域名登录：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093226-1.webp&amp;size=m" alt="1ed1f3aeb85b7de9289c25f921a40340.png"></p>
<p>默认用户名：<code>admin</code>
 <br>
 密码：<code>OVoPTw5B</code></p>
<p>这个等下都可以自己修改。</p>
<p>登录之后发现是这样的，因为我们还没有添加任何的存储源：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093224-1.webp&amp;size=m" alt="b569358ee1fefe1b457c6c173dbf1ce7.png"></p>
<p>点击首页下方的管理，来到后台。</p>
<p>我们来演示一下"添加存储"的操作，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093221-1.webp&amp;size=m" alt="eed7a56a23a3f2fa0269ee851714737d.png"></p>
<p>这边先选择一个"本地存储"，</p>
<p>挂载路径这边可以自己自定义，</p>
<p>WebDAV策略选择“本地代理”就行，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093219-1.webp&amp;size=m" alt="919e9cc5a6bab65898daa321583a3e65.png"></p>
<p>根文件夹路径要填docker容器内部的路径，这边前面我们在<code>docker-compose.yml</code>里面映射了<code>./share:/opt/openlist/share</code>，所以其实这边填<code>/opt/openlist/share</code>即可。</p>
<p>其他的选项按需自己设置。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093211-1.webp&amp;size=m" alt="699adef16557fd910c5120f59f020c84.png"></p>
<p>点击保存之后，再返回首页，就有显示了，后续可以自己把文件传到服务器，这边就会显示出来了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093208-1.webp&amp;size=m" alt="293e180d47b86f783314960b790c9935.png"></p>
<p>当然，AList之所以火爆，就是因为他可以添加很多个网盘的索引，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093206-1.webp&amp;size=m" alt="78a73028105f168bc635347f0a2265eb.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093205-1.webp&amp;size=m" alt="0dce80aeb7a0f61fe8c8a0105e26c227.png"></p>
<p>因为不同的小伙伴用的网盘也不一样，具体的细节，大家可以参考官方的文档来添加：<a href="https://docs.oplist.org/zh/guide/drivers/common.html">https://docs.oplist.org/zh/guide/drivers/common.html</a></p>
<h3 id="7-1-更新-openlist">7.1 更新 openlist</h3>
<pre><code class="language-yaml">cd /root/data/docker_data/openlist

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="7-2-卸载-openlist">7.2 卸载 openlist</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/openlist

docker compose down

cd ..

rm -rf /root/data/docker_data/openlist  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="8--常见问题及注意点">8. 常见问题及注意点</h2>
<p>目前 OpenList 已经发布了 4.0 正式版，但依然存在一些已知问题，不过大部分功能已可稳定使用，具体迁移进度可在 <a href="https://github.com/OpenListTeam/OpenList/issues/6">OpenList 迁移工作总结</a> 中查看。</p>
<p>大家记得多多更新，使用最新版本的docker镜像。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F07%2F04%2F093202-1.webp&amp;size=m" alt="a17367ce1aa891a163371be6f72c8b9f.png"></p>
<p>目前项目的赞助页面还未建立：<a href="https://docs.oplist.org/zh/zh/guide/sponsor.html">https://docs.oplist.org/zh/zh/guide/sponsor.html</a></p>
<p>后续建立了我也会支持，同时也希望有条件的小伙伴多多支持，赞赏开发者们一杯咖啡。这样也能让开源项目能够健康生存下去，少受商业的裹挟。</p>
<h2 id="9--结尾">9. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/OpenListTeam/OpenList/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，项目处于初期，有能力给项目做贡献的同学，也欢迎积极加入到 [项目]https://github.com/OpenListTeam/OpenList) 中来，贡献自己的一份力量！</p>
<p>最后，感谢开发人员们的辛苦付出，让我们能用到这么优秀的项目！也希望开源项目越来越好！</p>
<h2 id="10--参考资料">10. 参考资料</h2>
<p>官方GitHub：<a href="https://github.com/OpenListTeam/OpenList">https://github.com/OpenListTeam/OpenList</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-openlist</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Fri, 4 Jul 2025 01:46:00 GMT</pubDate></item><item><title><![CDATA[保护图片隐私！十分钟搭建一个小而美的离线图片处理工具——mazanoke｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-mazanoke</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E4%BF%9D%E6%8A%A4%E5%9B%BE%E7%89%87%E9%9A%90%E7%A7%81%EF%BC%81%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%B0%8F%E8%80%8C%E7%BE%8E%E7%9A%84%E7%A6%BB%E7%BA%BF%E5%9B%BE%E7%89%87%E5%A4%84%E7%90%86%E5%B7%A5%E5%85%B7%E2%80%94%E2%80%94mazanoke%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-mazanoke" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>之前和大家分享过：<a href="https://blog.laoda.de/archives/docker-compose-install-reubah">一个本地化图片处理工具——Reubah</a></p>
<p>今天我们再来分享一个UI更简洁漂亮的支持docker自建的本地图像处理工具——mazanoke</p>
<h2 id="2--mazanoke简介">2. mazanoke简介</h2>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105022-1.webp&amp;size=m" alt="1199394abe5998fca4e955a6de88e657.png"></p>
<p>MAZANOKE 是一个简单的图像优化工具，可以在你的浏览器中运行，离线工作，并且始终保持你的图像私密，是市面上那些宣传“免费”在线图片处理工具的替代品。</p>
<h3 id="2-1-功能">2.1 功能</h3>
<h4 id="---在浏览器中优化图像">🖼️ 在浏览器中优化图像</h4>
<ul>
 <li>调整图像质量</li>
 <li>设置目标文件大小</li>
 <li>设置最大宽度/高度</li>
 <li>从剪贴板粘贴图像</li>
 <li>在 JPG、PNG、WebP 之间转换</li>
 <li>从 HEIC、AVIF、GIF、SVG 转换</li>
</ul>
<h4 id="--注重隐私">🔒 注重隐私</h4>
<ul>
 <li>离线工作</li>
 <li>设备内处理图像</li>
 <li>删除 EXIF 数据（位置、日期等）</li>
 <li>无追踪</li>
 <li>可安装的网络应用程序</li>
</ul>
<h4 id="计划中的功能">计划中的功能</h4>
<ul>
 <li>一次上传多个文件</li>
 <li>支持更多图像文件类型
  <ul>
   <li>最近添加了从：HEIC、AVIF、GIF、SVG → JPG/PNG/WebP 的转换</li>
  </ul></li>
 <li>记住上次使用的设置</li>
 <li>裁剪图片</li>
</ul>
<h3 id="2-2-使用">2.2 使用</h3>
<p>官方Demo地址：<a href="https://mazanoke.com/">MAZANOKE.com</a></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105032-1.webp&amp;size=m" alt="cc6769191e8b166df0677018f4d76af8.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105036-1.webp&amp;size=m" alt="29a023ebea96d7dcb6b64e30898cf42a.png"></p>
<p>所见即所得，不多赘述。</p>
<p>其实，这个本质就是一个html页面，你可以直接点击右上角下载，这样就能离线使用了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105110-1_1.webp&amp;size=m" alt="85e4bd6fbe3b94f1eb19ed78fcaa0eb8.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105110-1.webp&amp;size=m" alt="45cc17bffdd5d8d699576a19c0cfd328.png"></p>
<p>或者是在这边下载：<a href="https://github.com/civilblur/mazanoke/releases">https://github.com/civilblur/mazanoke/releases</a></p>
<p>然后打开里面的<code>index.html</code>也可以直接离线使用。</p>
<p>当然如果你看到这边还想自己用docker搭建一个，那我们就继续往下！</p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/civilblur/mazanoke">https://github.com/civilblur/mazanoke</a> (目前1K个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的<a href="http://gao.ee/lca">莱卡云服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/mazanoke

cd /root/data/docker_data/mazanoke
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml"># Basic compose file for deploying MAZANOKE

services:
  mazanoke:
    container_name: mazanoke
    image: ghcr.io/civilblur/mazanoke:latest
    ports:
      - "3474:80"
  restart: unless-stopped
</code></pre>
<p>其中的左边的<code>3474</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3474</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3474  #查看 3474 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-mazanoke">6.4 启动 mazanoke</h3>
<pre><code>cd /root/data/docker_data/mazanoke

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3474</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105106-1.webp&amp;size=m" alt="dbbf5fa382d005f7f413603b4c0238f9.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105056-1.webp&amp;size=m" alt="546316e8d575d6f70533e1e09eb412cd.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205949-1.webp&amp;size=m" alt="c2075b8e6a85bff585396fd4c0bca1ed.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F05%2F09%2F105051-1.webp&amp;size=m" alt="6cc81ae5550620c5aaf8444ab60ac58e.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205935-1.webp&amp;size=m" alt="f5137b06b270769cc2ebca7019f47e35.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3474</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 mazanoke 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 mazanoke 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3474/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，所见即所得。</p>
<h3 id="8-1-更新-mazanoke">8.1 更新 mazanoke</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/mazanoke

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-mazanoke">8.2 卸载 mazanoke</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/mazanoke

docker compose down

cd ..

rm -rf /root/data/docker_data/mazanoke  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/civilblur/mazanoke/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/civilblur/mazanoke/mazanoke">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者<a href="https://github.com/civilblur/mazanoke">@civilblur</a>的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star ⭐️</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/civilblur/mazanoke">https://github.com/civilblur/mazanoke</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-mazanoke</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Fri, 9 May 2025 02:56:04 GMT</pubDate></item><item><title><![CDATA[10分钟搭建一个高颜值的在线开发工具箱—— jisuxiang｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-jisuxiang</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=10%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E9%AB%98%E9%A2%9C%E5%80%BC%E7%9A%84%E5%9C%A8%E7%BA%BF%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E7%AE%B1%E2%80%94%E2%80%94%20jisuxiang%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-jisuxiang" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>之前和大家分享过<a href="https://blog.laoda.de/archives/docker-compose-install-it-tools">【好玩儿的Docker项目】10分钟搭建一个高颜值的在线工具箱，用户体验很棒！</a>，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162922-1.webp&amp;size=m" alt="6bae1f25866c4f1b60943721f69796c1.png"></p>
<p>功能很丰富，不过不支持中文。</p>
<p>这一期来介绍一个中文的，高颜值的在线开发工具箱。</p>
<h2 id="2--jisuxiang简介">2. jisuxiang简介</h2>
<p>极速箱是一个高颜值的在线开发工具箱，提供各种程序员必备的开发工具，帮助开发者提升编程效率。本项目使用 Next.js 和 TailwindCSS 开发，拥有美观现代的界面设计。</p>
<p>在线演示: <a href="https://www.jisuxiang.com/">https://www.jisuxiang.com</a> - 立即体验！</p>
<h3 id="2-1---功能特点">2.1 🚀 功能特点</h3>
<ul>
 <li><strong>多种分类工具</strong>：JSON处理、编码解码、网络测试等多种实用工具</li>
 <li><strong>响应式设计</strong>：适配各种设备尺寸，提供最佳用户体验</li>
 <li><strong>暗色主题</strong>：保护眼睛的界面设计，适合长时间使用</li>
 <li><strong>高效搜索</strong>：快速找到所需工具的强大搜索功能</li>
 <li><strong>收藏系统</strong>：保存常用工具，方便快速访问</li>
 <li><strong>多语言支持</strong>：支持中文和英文界面</li>
</ul>
<h3 id="2-2---包含工具">2.2 🔧 包含工具</h3>
<ul>
 <li>JSON格式化与验证</li>
 <li>HTTP请求测试</li>
 <li>时间戳转换</li>
 <li>编码解码工具</li>
 <li>正则表达式测试</li>
 <li>加密解密工具</li>
 <li>颜色选择与转换</li>
 <li>代码格式化</li>
 <li>JSON编辑器与转换器</li>
 <li>IP地址查询</li>
 <li>日期计算器</li>
 <li>时区转换</li>
 <li>文本统计</li>
 <li>HTML/Markdown转换</li>
 <li>图片压缩</li>
 <li>二维码生成</li>
 <li>CSS渐变生成器</li>
 <li>更多实用工具...</li>
</ul>
<h3 id="2-3-使用">2.3 使用</h3>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162919-1.webp&amp;size=m" alt="c86398679044dcdd3df5487fe7c0d560.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162918-1.webp&amp;size=m" alt="338c4db9517abac9b37cdc226113f745.png">
 <br>
 当然如果你看到这边想自己搭建一个，那我们就继续往下看！</p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/star7th/jisuxiang">https://github.com/star7th/jisuxiang</a> (目前261个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的香港的<a href="https://loll.cc/tx">腾讯云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/jisuxiang

cd /root/data/docker_data/jisuxiang
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">name: jisuxiang
services:
    jisuxiang:
        container_name: jisuxiang
        restart: always
        ports:
            - 3001:3000
        image: star7th/jisuxiang:latest
</code></pre>
<p>其中的左边的<code>3001</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3001</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3001  #查看 3001 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-jisuxiang">6.4 启动 jisuxiang</h3>
<pre><code>cd /root/data/docker_data/jisuxiang

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3001</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F163004-1.webp&amp;size=m" alt="image-20250422163001796"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162853-1.webp&amp;size=m" alt="9a1e1688e15e1fa88303c4df48fdb85b.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162851-1.webp&amp;size=m" alt="f49627216cee515fab28d95eac05b6f9.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162849-1.webp&amp;size=m" alt="9da4948e39b0777b72d7785d76b26cd6.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F22%2F162841-1.webp&amp;size=m" alt="c26132063961e0de1048995075192bca.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3001</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 jisuxiang 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 jisuxiang 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3001/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<p>非常简单，开箱即用。</p>
<h3 id="8-1-更新-jisuxiang">8.1 更新 jisuxiang</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/jisuxiang

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-2-卸载-jisuxiang">8.2 卸载 jisuxiang</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/jisuxiang

docker compose down

cd ..

rm -rf /root/data/docker_data/jisuxiang  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>暂时没有。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/star7th/jisuxiang/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/star7th/jisuxiang">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者<a href="https://github.com/star7th/jisuxiang">@star7th</a>的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star ⭐️</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/star7th/jisuxiang">https://github.com/star7th/jisuxiang</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-jisuxiang</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Tue, 22 Apr 2025 08:34:56 GMT</pubDate></item><item><title><![CDATA[Docker 一键部署网盘资源搜索与转存工具——CloudSaver｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-cloudsaver</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=Docker%20%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2%E7%BD%91%E7%9B%98%E8%B5%84%E6%BA%90%E6%90%9C%E7%B4%A2%E4%B8%8E%E8%BD%AC%E5%AD%98%E5%B7%A5%E5%85%B7%E2%80%94%E2%80%94CloudSaver%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-cloudsaver" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>最近事情比较多，很长时间没和大家分享好玩儿的Docker项目了，今天来分享一个网盘资源搜索与转存工具——CloudSaver</p>
<h2 id="2--cloudsaver简介">2. cloudsaver简介</h2>
<ul>
 <li>🔍 多源资源搜索
  <ul>
   <li>支持多个资源订阅源搜索</li>
   <li>支持关键词搜索与资源链接解析</li>
   <li>支持豆瓣热门榜单展示</li>
  </ul></li>
 <li>💾 网盘资源转存
  <ul>
   <li>支持 <code>115 网盘</code>，<code>夸克网盘</code>，<code>天翼网盘</code> 一键转存</li>
   <li>支持转存文件夹展示与选择</li>
  </ul></li>
 <li>👥 多用户系统
  <ul>
   <li>支持用户注册登录</li>
   <li>支持管理员与普通用户权限区分</li>
  </ul></li>
 <li>📱 响应式设计
  <ul>
   <li>支持 <code>PC</code> 端与移动端自适应布局</li>
   <li>针对不同设备优化的交互体验</li>
  </ul></li>
</ul>
<h2 id="2-1-特别声明">2.1 特别声明</h2>
<ol>
 <li>本项目仅供学习交流使用，请勿用于非法用途</li>
 <li>仅支持个人使用，不支持任何形式的商业使用</li>
 <li>禁止在项目页面进行任何形式的广告宣传</li>
 <li>所有搜索到的资源均来自第三方，本项目不对其真实性、合法性做出任何保证</li>
</ol>
<h2 id="2-2-使用">2.2 使用</h2>
<p>热门榜单</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210035-1.webp&amp;size=m" alt="e8f72be3818444f667dca127dc190bdf.png"></p>
<p>资源搜索</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210031-1.webp&amp;size=m" alt="8fe62b57d3302defa6ba13cfcd6de7df.png"></p>
<p>比如搜一个“甄嬛传”</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210028-1.webp&amp;size=m" alt="9da44b07d7a5766171322a01b8e89ffc.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210024-1.webp&amp;size=m" alt="ed735f7e731c8bc0f19ce0c1885226e4.png"></p>
<p>转存</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210022-1.webp&amp;size=m" alt="a8712fdc4810b3db84ecb00a8009c4f7.png" style="zoom:50%;">
<p>转存成功</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210012-1.webp&amp;size=m" alt="4967cf7578df6a02493cc3a2376f5b6f.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210008-1.webp&amp;size=m" alt="6714b19a5272c1d86f9e0c40f1386eaf.png"></p>
<p>当然如果你看到这边想自己搭建一个，那我们就继续往下看！</p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/jiangrui1994/cloudsaver">https://github.com/jiangrui1994/cloudsaver</a> (目前3.6K个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：这边强烈建议用非大陆的服务器，不然必须要启用代理设置，否则会刷不到任何内容，咕咕这边用的香港的<a href="https://loll.cc/tx">腾讯云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/cloudsaver

cd /root/data/docker_data/cloudsaver
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  cloudsaver:
    image: jiangrui1994/cloudsaver:latest
    container_name: cloud-saver
    ports:
      - "8009:8008"
    volumes:
      - ./data:/app/data
      - ./config:/app/config
    restart: unless-stopped
</code></pre>
<p>其中的左边的<code>8009</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>8009</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:8009  #查看 8009 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-cloudsaver">6.4 启动 cloudsaver</h3>
<pre><code>cd /root/data/docker_data/cloudsaver

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:8009</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F210003-1.webp&amp;size=m" alt="763a1f9516de8f3696de76b708488a6b.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205956-1.webp&amp;size=m" alt="014632b85d0fda607f46f81e0ec796fa.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205949-1.webp&amp;size=m" alt="c2075b8e6a85bff585396fd4c0bca1ed.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205943-1.webp&amp;size=m" alt="09174f6d6ad957739017f97f42d7d184.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205935-1.webp&amp;size=m" alt="f5137b06b270769cc2ebca7019f47e35.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>8009</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 cloudsaver 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 cloudsaver 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:8009/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<h3 id="8-1-搜索与转存资源">8.1 搜索与转存资源</h3>
<p>登陆，开始注册。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205919-1.webp&amp;size=m" alt="9af544f6a382375205d3e75c249aa659.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205910-1.webp&amp;size=m" alt="902ac98e6625f92856d6a3da78ae9958.png"></p>
<p>默认注册码：</p>
<ul>
 <li>管理员：<code>230713</code></li>
 <li>普通用户：<code>9527</code></li>
</ul>
<p>我们是管理员就用<code>230713</code></p>
<p>为了安全起见，登陆之后第一件事情就去更改一下默认的注册码。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205902-1.webp&amp;size=m" alt="2f41c48836c96cf2d7d25cc28d06676b.png"></p>
<h3 id="8-2-115-网盘-cookie获取">8.2 115 网盘 cookie获取</h3>
<p>用户配置，这边就是看你转存到哪个网盘，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205854-1.webp&amp;size=m" alt="89f9fae000c28e144b7c346959186a7f.png"></p>
<p>这边我们以115网盘为例子：</p>
<ul>
 <li>从网页登录 <code>115网盘</code>；</li>
 <li>按 <code>F12</code> 打开 <code>开发者工具</code>；</li>
 <li>在<code>Network</code> –&gt; <code>Filter</code> 中输入 <code>get</code>，找到 <code>warning_get</code>，就可以获取到 <code>cookie</code> 的值；</li>
</ul>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205744-1.webp&amp;size=m" alt="915a61376931f64e734453c150f25318.png"></p>
<p>如果115网盘空间不够，可以扫码开通会员，年付158元，可以扩容至5T。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F205731-1.webp&amp;size=m" alt="IMG_6982.JPG" style="zoom:33%;">
<h3 id="8-3-更新-cloudsaver">8.3 更新 cloudsaver</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/cloudsaver

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-4-卸载-cloudsaver">8.4 卸载 cloudsaver</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/cloudsaver

docker compose down

cd ..

rm -rf /root/data/docker_data/cloudsaver  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>咕咕实测，115资源最多，其他俩网盘有些资源可能失效。</p>
<p>另外，本项目仅供学习交流使用，请勿用于非法用途。</p>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/jiangrui1994/cloudsaver/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/jiangrui1994/cloudsaver/cloudsaver">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star ⭐️</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/jiangrui1994/cloudsaver">https://github.com/jiangrui1994/cloudsaver</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-cloudsaver</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F211404.webp&amp;size=m" type="image/jpeg" length="61218"/><category>Docker系列</category><pubDate>Wed, 16 Apr 2025 13:15:51 GMT</pubDate></item><item><title><![CDATA[想用大厂的云服务器，如何省心又省钱？试试新加坡的云服务器代理商——Huichang Cloud]]></title><link>https://blog.laoda.de/archives/huichang-cloud</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E6%83%B3%E7%94%A8%E5%A4%A7%E5%8E%82%E7%9A%84%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E5%A6%82%E4%BD%95%E7%9C%81%E5%BF%83%E5%8F%88%E7%9C%81%E9%92%B1%EF%BC%9F%E8%AF%95%E8%AF%95%E6%96%B0%E5%8A%A0%E5%9D%A1%E7%9A%84%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BB%A3%E7%90%86%E5%95%86%E2%80%94%E2%80%94Huichang%20Cloud&amp;url=/archives/huichang-cloud" width="1" height="1" alt="" style="opacity:0;">
<h2 id="云服务器代理商是个啥-">云服务器代理商是个啥？</h2>
<p>简单来说，<a href="https://huichangcloud.com">云服务器代理商</a>就是帮你搞定云服务器的“中间人”。你想用<a href="https://huichangcloud.com/ali/">阿里云</a>、<a href="https://huichangcloud.com/tencent/">腾讯云</a>这些大厂的服务器，但直接去官网买，可能觉得价格偏高，或者有些用户想要匿名购买或者是用加密货币或者美元购买。代理商呢，就相当于你的“云服务管家”，可以帮你选服务器、开账号、搞优惠，还能提供技术支持。省心省力，关键还能省钱！（他们虽然给你85折的充值优惠，但是由于走的渠道，你的账号是和他们关联的，他们还是有的赚！）</p>
<h2 id="为啥选阿里云国际-腾讯云国际的服务器-">为啥选阿里云国际、腾讯云国际的服务器？</h2>
<p><a href="https://huichangcloud.com/ali/">阿里云国际</a>和<a href="https://huichangcloud.com/tencent/">腾讯云国际</a>有啥优势?</p>
<ol>
 <li><strong>全球覆盖，速度快</strong>：不管你的业务在亚洲、欧洲还是美洲，这两家都有遍布全球的数据中心。尤其是新加坡节点，延迟低到飞起，特别适合东南亚市场的朋友。</li>
 <li><strong>稳定如老狗</strong>：大厂的服务器，硬件和网络都比较靠谱，宕机的概率比你家Wi-Fi断网还低。</li>
 <li><strong>功能多到炸</strong>：从存储、计算到AI、大数据，啥都能干。想搭网站、跑应用、存数据，都能搞定。</li>
 <li><strong>安全性拉满</strong>：防火墙、DDoS防护、数据加密，为你的业务保驾护航。</li>
</ol>
<h2 id="代理开户的优势">代理开户的优势</h2>
<p>用大厂的机器，基本上就是“稳中带快，啥都能干”。但直接买，可能有点烧钱，这时候找个靠谱代理就显得特别重要了。</p>
<p>代理开户的优势如下：</p>
<ul>
 <li><strong>省钱第一名</strong>：代理商跟云厂商关系铁，能拿到大额折扣，即使扣除了他们自己赚的那部分，也比你自己官网充值便宜一大截。</li>
 <li><strong>省心省力</strong>：提供匿名账号，保护客户隐私，免实名，免绑卡，从注册账号到配置服务器，代理帮你一条龙搞定。</li>
 <li><strong>售后有保障</strong>：官网的客服有时候回复比较慢，代理商的响应速度快多了，随时帮你解决问题。</li>
 <li><strong>灵活选择</strong>：代理商通常能提供更灵活的套餐，甚至还能定制，满足你的各种奇葩需求。</li>
</ul>
<p>一句话，找代理就像找了个“云服务经纪人”，可以让你少走一点弯路，直接享受VIP待遇。</p>
<h2 id="认识一下Huichang-Cloud-来自新加坡的代理-">认识一下Huichang Cloud，来自新加坡的代理！</h2>
<p>新加坡的云服务器代理——<strong><a href="https://huichangcloud.com">Huichang Cloud</a></strong> 在圈子里口碑不错，服务覆盖阿里云国际、腾讯云国际、AWS、华为云等大牌。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084221-1.webp&amp;size=m" alt="fe818c868c022dbc065486fb8eaa7e35.png"></p>
<p>为什么选他们？</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084212-1.webp&amp;size=m" alt="3499d60bdcdbd9b6f6c87325edd7b404.png"></p>
<ol>
 <li><strong>折扣大</strong></li>
</ol>
<p><a href="https://huichangcloud.com">Huichang Cloud</a>跟云厂商深度合作，折扣力度能低到5折！买同样的配置，别人花一万，你可能只要五千。尤其是对于云服务器大户，一年下来可以省不少钱。</p>
<ol start="2">
 <li><strong>账号稳</strong></li>
</ol>
<p>用过云服务器的朋友可能遇到过账号被封的糟心事。<a href="https://huichangcloud.com">Huichang Cloud</a>的代理渠道账号稳定，合规操作，基本不用担心突然“人间蒸发”。</p>
<ol start="3">
 <li><strong>从开户到售后，一站式服务</strong></li>
</ol>
<p>不管你是小白还是老手，他们从账号注册、服务器选配到后期维护，全程陪跑。遇到问题？直接找他们，效率更高。</p>
<ol start="4">
 <li><strong>原厂工程师坐镇</strong></li>
</ol>
<p><a href="https://huichangcloud.com">Huichang Cloud</a>的技术团队里有不少来自云厂商原厂的工程师，经验老道。不管是优化服务器性能，还是处理突发故障，他们都能给你稳稳地解决。</p>
<p>想了解更多细节，或者直接上手试试？</p>
<p>可以通过<a href="https://t.me/hfcloud88">Telegram</a>/<a href="https://api.whatsapp.com/send?phone=85252699909">Whatsapp</a>/QQ（QQ群：901579741），联系到Huichang Cloud，里面有客服随时答疑。</p>
<p><strong>如果充值购买，联系客服报优惠码<code>gugu</code>，可以获得额外5%的充值优惠。</strong></p>
<h2 id="聊聊体验">聊聊体验</h2>
<p>我特意去试了试<a href="https://huichangcloud.com">Huichang Cloud</a>的服务，打算选个阿里云国际的香港节点服务器。</p>
<p>这边直接点击<a href="https://huichangcloud.com">官网链接</a>，通过Bot机器人充值（（建议可以都先联系一下客服再充值），</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084216-1.webp&amp;size=m" alt="3f8f9fcc37b5459df83cade97c0bf609.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084207-1.webp&amp;size=m" alt="5c3c86602790f6cb66c355c872bb7907.png"></p>
<p>或者联系客服充值，（可以通过<a href="https://t.me/hfcloud88">Telegram</a>/<a href="https://api.whatsapp.com/send?phone=85252699909">Whatsapp</a>/QQ（QQ群：901579741），联系到Huichang Cloud客服）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084205-1.webp&amp;size=m" alt="bf391a326cbc80c488d6477de61b31b9.png"></p>
<p>之后会直接给到账户密码，用于直接在阿里云国际站官网登录。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084204-1.webp&amp;size=m" alt="646fd74b6e0d59c986c71ac5cf36e470.png" style="zoom:50%;">
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084156-1.webp&amp;size=m" alt="26f492372eed1045e115cc3979f5dde6.png"></p>
<p>登录：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084154-1.webp&amp;size=m" alt="916baf0f7a8f80339a24df24044e6b87.png"></p>
<p>选择通过邮箱认证：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084151-1.webp&amp;size=m" alt="9d2a2e65819024ceec3b0844e5e0287d.png"></p>
<p>然后登录邮箱查看验证码：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084154-1_1.webp&amp;size=m" alt="1e2b06605d26b5f50514cec90f09be28.png"></p>
<p>登录之后来到控制台，就可以开始选购服务了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084151-1_1.webp&amp;size=m" alt="8fde9f641fd4588846698c263eefdff5.png"></p>
<p>轻量云选购页面：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084146-1.webp&amp;size=m" alt="ec015ad658e27443340d35cdfa293bec.png"></p>
<p>接下来就是正常和用阿里云一样使用就可以了。</p>
<p>当然，如果你有需求，也可以把账号绑定的手机号和邮箱改成自己的。</p>
<p>注意：更换手机号需要找客服拿到原来手机号的验证码并且只能更换同地区的手机号</p>
<p>全流程大概梳理如下：</p>
<blockquote>
 <p>通过Telegram、Whatsapp、qq，联系到Huichang Cloud——告诉Huichang Cloud需求（需要哪里的服务器）——付款（美元、USDT、RMB，这边会有相应的折扣）——Huichang Cloud 提供一个充值完成的成品账号，里面包含腾讯或者阿里的云服务器国际站官网的登录信息+对应绑定邮箱的登录信息（用于接收验证码）——用户利用该信息登录国际云的官网，进行服务器的购买操作（里面已经充值过了对应的金额）——后续用户可以根据自己的需求选择是否更换绑定的邮箱和手机号，更换手机号需要找客服拿到原来手机号的验证码并且只能更换同地区的手机号</p>
</blockquote>
<p>总的来说，体验下来，<a href="https://huichangcloud.com">Huichang Cloud</a>还是比较“靠谱+省心”的。</p>
<h2 id="最后">最后</h2>
<p>云服务器这玩意儿，选对了服务商，可以让你省不少事儿，少踩一堆坑。<a href="https://huichangcloud.com">Huichang Cloud</a>作为新加坡的实力派代理，折扣给力、服务贴心，挺值得一试。不管你是想搭个博客、跑个电商网站，还是搞点更复杂的业务，他们都能帮你安排得明明白白。国内小伙伴有需求的可以加入他们的<strong>QQ群：901579741</strong> 咨询更多细节。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F084128-1.webp&amp;size=m" alt="48032968dca6e5b08f37ab9f1c5eb4a4.png" style="zoom:33%;">
<p>海外小伙伴可以通过<a href="https://t.me/hfcloud88">Telegram</a>/<a href="https://api.whatsapp.com/send?phone=85252699909">Whatsapp</a>，联系到Huichang Cloud，里面有客服随时答疑。</p>]]></description><guid isPermaLink="false">/archives/huichang-cloud</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F13%2F092043-1.webp&amp;size=m" type="image/jpeg" length="91264"/><category>VPS推荐</category><pubDate>Sun, 13 Apr 2025 01:22:47 GMT</pubDate></item><item><title><![CDATA[让写简历变得简单且智能！十分钟搭建一个在线简历编辑器——Magic Resume｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-magic-resume</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E8%AE%A9%E5%86%99%E7%AE%80%E5%8E%86%E5%8F%98%E5%BE%97%E7%AE%80%E5%8D%95%E4%B8%94%E6%99%BA%E8%83%BD%EF%BC%81%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%9C%A8%E7%BA%BF%E7%AE%80%E5%8E%86%E7%BC%96%E8%BE%91%E5%99%A8%E2%80%94%E2%80%94Magic%20Resume%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-magic-resume" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>关注咕咕频道的有不少小伙伴还在大学念书，这一期我们带来一个实用的项目——帮助你轻松搞定一份简历！</p>
<h2 id="2--magic-resume简介">2. magic-resume简介</h2>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162808-1.webp&amp;size=m" alt="f20b9633c197466de36998111097a76a.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162804-1.webp&amp;size=m" alt="5d0fc094f1f8bde6c7c94428c702fa5e.png"></p>
<h3 id="现有特性">现有特性</h3>
<ul>
 <li>🚀 基于 Next.js 14+ 构建</li>
 <li>💫 流畅的动画效果 (Framer Motion)</li>
 <li>🎨 自定义主题支持</li>
 <li>📱 响应式设计</li>
 <li>🌙 深色模式</li>
 <li>📤 导出为 PDF</li>
 <li>🔄 实时预览</li>
 <li>💾 自动保存</li>
 <li>🔒 本地存储</li>
</ul>
<h3 id="后续升级路线">后续升级路线</h3>
<ul>
 <li class="vditor-task vditor-task--done"><input checked disabled type="checkbox"> AI 辅助编写</li>
 <li class="vditor-task vditor-task--done"><input checked disabled type="checkbox"> 多语言支持</li>
 <li class="vditor-task"><input disabled type="checkbox"> 支持更多简历模板</li>
 <li class="vditor-task"><input disabled type="checkbox"> 更多格式导出</li>
 <li class="vditor-task"><input disabled type="checkbox"> 自定义模型</li>
 <li class="vditor-task"><input disabled type="checkbox"> 智能一页</li>
 <li class="vditor-task"><input disabled type="checkbox"> 导入 PDF, Markdown 等</li>
 <li class="vditor-task"><input disabled type="checkbox"> 在线简历托管</li>
</ul>
<h3 id="使用">使用</h3>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162758-1.webp&amp;size=m" alt="f20b9633c197466de36998111097a76a.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162755-1.webp&amp;size=m" alt="0335a33ed59638de482c118eed96afc7.png"></p>
<p>里面有常用的一些模版，可以选一个自己喜欢的，直接套用：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162750-1.webp&amp;size=m" alt="25b9cd2430d699ac26dd50046f79c532.png"></p>
<p>支持文件夹同步：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162747-1.webp&amp;size=m" alt="247893858deebecd7c2ac4f301c51606.png"></p>
<p>AI 辅助编写的功能已经上线，模型目前支持豆包和deepseek：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162745-1.webp&amp;size=m" alt="5be0a217d2bc6e45f788f881afc54a6b.png"></p>
<p>简历的编辑页面是这样的：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162744-1.webp&amp;size=m" alt="ff0fc68e54003a82075149f5211b91ff.png"></p>
<p>功能非常丰富，所见即所得：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162742-1.webp&amp;size=m" alt="e5602952d110ea46b65e3d1a1b5e645d.png"></p>
<p>其实这个项目大家不用自己搭，可以直接使用作者搭好的Demo，Demo地址：<a href="https://magicv.art/app/dashboard/resumes">https://magicv.art/app/dashboard/resumes</a></p>
<p>当然如果你看到这边想自己搭建一个，那我们就继续往下看！</p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/JOYCEQL/magic-resume">https://github.com/JOYCEQL/magic-resume</a> (目前937个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：这边强烈建议用非大陆的服务器，不然很多网站访问不了，咕咕这边用的香港的<a href="https://loll.cc/tx">腾讯云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/magic-resume

cd /root/data/docker_data/magic-resume
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  web:
    image: siyueqingchen/magic-resume:main
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    restart: always
</code></pre>
<p>其中的左边的<code>3000</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3000</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3000  #查看 3000 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-magic-resume">6.4 启动 magic-resume</h3>
<pre><code>cd /root/data/docker_data/magic-resume

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3000</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F163330-1.webp&amp;size=m" alt="4d2314e0c40d184b1a0cec5f34090b8a.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162734-1.webp&amp;size=m" alt="34aa06ba800fcdb0326ce3119f935500.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162729-1.webp&amp;size=m" alt="326e2860f6e6add70d2e5b13f9f7bb74.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162723-1.webp&amp;size=m" alt="1ce8c9e7098eda43319b44aa3201cb26.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162716-1.webp&amp;size=m" alt="aaa2938d536a1ad5b876e1a268731600.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3000</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 magic-resume 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 magic-resume 所在的服务器 IP 就行。</p>
<p>然后访问域名就可以访问了！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F14%2F162704-1.webp&amp;size=m" alt="ceca284eca4b21300a8f6da7642b6a6d.png"></p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3000/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<h2 id="8-1-编辑简历">8.1 编辑简历</h2>
<p>见视频或者自己琢磨一下，很简单。</p>
<h3 id="8-2-更新-magic-resume">8.2 更新 magic-resume</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/magic-resume

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-3-卸载-magic-resume">8.3 卸载 magic-resume</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/magic-resume

docker compose down

cd ..

rm -rf /root/data/docker_data/magic-resume  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>咕咕个人感觉完成度已经挺高了，AI模型目前暂时只支持豆包和deepseek，后续可以考虑加入自定义或者海外的几个模型，走向国际化！</p>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/JOYCEQL/magic-resume/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/JOYCEQL/magic-resume/magic-resume">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢作者<a href="https://github.com/JOYCEQL/magic-resume">@JOYCEQL</a>的辛苦付出，让我们能用到这么优秀的项目！欢迎大家都去给这个项目点个 star ⭐️</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/JOYCEQL/magic-resume">https://github.com/JOYCEQL/magic-resume</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-magic-resume</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F04%2F16%2F212221.webp&amp;size=m" type="image/jpeg" length="44534"/><category>Docker系列</category><pubDate>Fri, 14 Mar 2025 08:36:36 GMT</pubDate></item><item><title><![CDATA[性价比神机！BandwagonHost 上新 MEGABOX PRO 套餐，AMD处理器 2T流量，三网线路优化！]]></title><link>https://blog.laoda.de/archives/bwg-megaboxpro</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E6%80%A7%E4%BB%B7%E6%AF%94%E7%A5%9E%E6%9C%BA%EF%BC%81BandwagonHost%20%E4%B8%8A%E6%96%B0%20MEGABOX%20PRO%20%E5%A5%97%E9%A4%90%EF%BC%8CAMD%E5%A4%84%E7%90%86%E5%99%A8%202T%E6%B5%81%E9%87%8F%EF%BC%8C%E4%B8%89%E7%BD%91%E7%BA%BF%E8%B7%AF%E4%BC%98%E5%8C%96%EF%BC%81&amp;url=/archives/bwg-megaboxpro" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p>2025年3月11日14:09分，已经卖完了 = =</p>
</blockquote>
<p>今天搬瓦工推出了一款性价比非常高的机器，这边和大家分享一下。</p>
<p>📦 搬瓦工上新 MEGABOX PRO 限量套餐，位于美国洛杉矶（DC1）数据中心，当前回程为电信/联通 CN2 GIA 线路，移动 CMIN2 线路。</p>
<p>CPU: 2 AMD vCore
 <br>
 内存: 2 GB
 <br>
 硬盘: 40 GB SSD
 <br>
 流量: 2000 GB @ 2.5 Gbps
 <br>
 🏷️ 价格: <span class="language-math">49.00/年（优惠后 </span>45.68/年）
 <br>
 🔖 优惠码: <code>BWHCGLUKKB</code> （6.77%）
 <br>
 🛒 购买链接： <a href="https://gao.ee/megaboxpro">https://gao.ee/megaboxpro</a></p>
<ul>
 <li>此前购买 BiggerBox Pro 的用户可后台补差价升级至该套餐。大家可以根据自己需要升级（直接升级貌似会贵2刀）或者再买一个。（之前的流量使用不到10%可以申请退款）</li>
</ul>
<p>我已经购入一台：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115839-1.webp&amp;size=m" alt="708e975cf1e00275a1f3318b714ef5a0.png"></p>
<h2 id="服务器综合测试">服务器综合测试</h2>
<p>测试脚本：</p>
<pre><code class="language-bash">export noninteractive=true &amp;&amp; curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh &amp;&amp; chmod +x goecs.sh &amp;&amp; bash goecs.sh env &amp;&amp; bash goecs.sh install &amp;&amp; goecs
</code></pre>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115837-1.webp&amp;size=m" alt="a80d35b0208ce62ab0f282156a00b9d5.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115834-1.webp&amp;size=m" alt="a7d7ff18b70a7a26e5b36c1c7e43e9c2.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115831-1.webp&amp;size=m" alt="2553043cb684fd8c514aa50563da6026.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115830-1.webp&amp;size=m" alt="79f79cbf2beeaf3bed64f8aaf6d43f28.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115827-1.webp&amp;size=m" alt="4e1117ae368e41a75ef920cfe8945bfa.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115825-1.webp&amp;size=m" alt="57c34abd6eef91e1246fb2e23cb0bffe.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115821-1.webp&amp;size=m" alt="4342f2c8a16acbc2c7b69f324c0fbdec.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115819-1.webp&amp;size=m" alt="de1b40862dcc53ff5f0bcd494770fc3d.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115816-1.webp&amp;size=m" alt="b1f23eb0755b021bbde25f3943bd6542.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F115814-1.webp&amp;size=m" alt="b66ef31b38a946b3500fc8c42d58513b.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F03%2F11%2F131104-1.webp&amp;size=m" alt="ed274b41e56d6a483157db6a458fd0ea.png"></p>
<p>测试详情URL：<a href="https://paste.spiritlhl.net/#/show/NzPRc.txt">https://paste.spiritlhl.net/#/show/NzPRc.txt</a></p>]]></description><guid isPermaLink="false">/archives/bwg-megaboxpro</guid><dc:creator>咕咕</dc:creator><category>VPS推荐</category><pubDate>Tue, 11 Mar 2025 04:00:01 GMT</pubDate></item><item><title><![CDATA[十分钟搭建一个带Web界面的yt-dlp视频下载器｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-yt-dlp-web-ui</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%B8%A6Web%E7%95%8C%E9%9D%A2%E7%9A%84yt-dlp%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD%E5%99%A8%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-yt-dlp-web-ui" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>yt-dlp 是一款基于 youtube-dl 开发的开源命令行视频下载工具，支持从 1000+ 个平台获取内容。它不仅能下载 YouTube 视频，还支持包括 B站、网易云音乐、Vimeo、Twitter 等主流平台。</p>
<h2 id="2--ytdlpwebui主要功能">2. ytdlpwebui主要功能</h2>
<p>这是一个基于 yt-dlp 的自托管 Web UI 和 RPC 服务项目，专为 NAS 和服务器环境设计。项目通过 Docker 容器提供轻量级部署（镜像体积仅 18MB），支持以下核心功能：</p>
<ol>
 <li><strong>多平台视频下载</strong>：支持 YouTube、B站等 1000+ 平台的视频/音频下载，可自动选择最高画质或手动指定格式</li>
 <li><strong>任务队列管理</strong>：通过 <code>--qs</code> 参数控制并发下载数量（默认 2 个并行任务）</li>
 <li><strong>远程控制接口</strong>：提供 JSON-RPC 1.0 API 和 WebSocket 实时状态推送，支持 JWT 认证（需配置 <code>--auth</code> 参数）</li>
 <li><strong>定制化前端</strong>：允许替换默认 Material 风格界面，自定义前端只需符合指定目录结构即可加载</li>
 <li><strong>系统集成</strong>：提供 Docker Compose 部署模板和 Systemd 服务配置方案，支持 SQLite 数据库存储任务记录</li>
</ol>
<p>典型应用场景包括 NAS 媒体库自动归档、直播流监控等，项目通过 <code>--driver</code> 参数可指定不同版本的 yt-dlp 执行文件，最新版本已适配 2025 年 YouTube 的 HDR10+ 格式下载需求。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175122-1.webp&amp;size=m" alt="b47c19f7b0599fc9e728df2366404ceb.png"></p>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/marcopiovanello/yt-dlp-web-ui">https://github.com/marcopiovanello/yt-dlp-web-ui</a> (全新项目，目前1.1个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：这边强烈建议用非大陆的服务器，不然很多网站访问不了，咕咕这边用的香港的<a href="https://loll.cc/tx">腾讯云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/ytdlpwebui

cd /root/data/docker_data/ytdlpwebui

mkdir config

cd config

vim config.yml
</code></pre>
<p>这边我们用最简单的认证方式（更多认证方式，可以参考<a href="https://github.com/marcopiovanello/yt-dlp-web-ui/wiki/Authentication-methods#usernamepassword-based-authentication">官方的wiki</a>），粘贴填入这些内容，其中<code>your_username</code>改成你自己的登录名字，<code>your_password</code>改成你的密码。</p>
<pre><code class="language-bash">require_auth: true
username: your_username
password: your_password
</code></pre>
<p>完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">cd ..
vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  yt-dlp-webui:
    image: marcobaobao/yt-dlp-webui
    ports:
      - 3035:3033
    volumes:
      - ./downloads:/downloads # replace &lt;your dir&gt; with a directory on your host system
      - ./config:/config    # directory where config.yml will be stored
    healthcheck:
      test: curl -f http://localhost:3033 || exit 1
    restart: unless-stopped
</code></pre>
<p>其中的<code>3035</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>3035</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:3035  #查看 3035 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-ytdlpwebui">6.4 启动 ytdlpwebui</h3>
<pre><code>cd /root/data/docker_data/ytdlpwebui

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:3035</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>gugugu</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175116-1.webp&amp;size=m" alt="78bd2f375284b97ce3005f5261f5cf1e.png"></p>
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175114-1.webp&amp;size=m" alt="b7744de575d56a2ebb3ff6f72ddb9a14.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175109-1.webp&amp;size=m" alt="68f8b8ec569c416bebb0369972704956.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175105-1.webp&amp;size=m" alt="dbfc25363e4400a63f6f629d3ee98753.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175101-1.webp&amp;size=m" alt="de63746abc189a0940269a00edd66e58.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>3035</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 ytdlpwebui 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 ytdlpwebui 所在的服务器 IP 就行。</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:3035/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<h2 id="8-1-下载视频">8.1 下载视频</h2>
<p>见视频或者自己琢磨一下，很简单。</p>
<p>输入网址之后，提示需要登录才可以使用，输入我们前面设置的账号密码</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175052-1.webp&amp;size=m" alt="f7c59d400ef2f8cd31674dbaebb2b92a.png"></p>
<p>首页是这个样子，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175050-1.webp&amp;size=m" alt="ff2ecca29d5ab68678780af3edf2886a.png"></p>
<p>设置部分，支持把语言改成中文的，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175049-1.webp&amp;size=m" alt="db58132d7d32d491bcf8720c3741b365.png"></p>
<p>选一个YouTube视频，可以尝试下载，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175047-1.webp&amp;size=m" alt="d397bc2f437dbe8b2111f356716afc08.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175046-1.webp&amp;size=m" alt="a1a53981654333871ec0077d26980a94.png"></p>
<p>下载成功之后，可以选择点击观看或者下载到本地观看了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175046-1_1.webp&amp;size=m" alt="ba5f25c004c3c08a5fcda8a63c27ffda.png"></p>
<h3 id="8-2-更新-ytdlpwebui">8.2 更新 ytdlpwebui</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/ytdlpwebui

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-3-卸载-ytdlpwebui">8.3 卸载 ytdlpwebui</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/ytdlpwebui

docker compose down

cd ..

rm -rf /root/data/docker_data/ytdlpwebui  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>目前发现推特和哔哩哔哩的视频下载完成之后会显示0B，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F19%2F175037-1.webp&amp;size=m" alt="59bcb9e71c8985def5a241d7bab30efc.png"></p>
<p>大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/marcopiovanello/yt-dlp-web-ui/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/marcopiovanello/yt-dlp-web-ui/ytdlpwebui">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢开发人员们的辛苦付出，让我们能用到这么优秀的项目！</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/marcopiovanello/yt-dlp-web-ui">https://github.com/marcopiovanello/yt-dlp-web-ui</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-yt-dlp-web-ui</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F22%2F161547.webp&amp;size=m" type="image/jpeg" length="48808"/><category>Docker系列</category><pubDate>Thu, 20 Feb 2025 00:53:06 GMT</pubDate></item><item><title><![CDATA[用M1 Max MacBook Pro私有化部署DeepSeek-R1]]></title><link>https://blog.laoda.de/archives/deploy-deepseek-r1-using-m1-max-macbook-pro</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E7%94%A8M1%20Max%20MacBook%20Pro%E7%A7%81%E6%9C%89%E5%8C%96%E9%83%A8%E7%BD%B2DeepSeek-R1&amp;url=/archives/deploy-deepseek-r1-using-m1-max-macbook-pro" width="1" height="1" alt="" style="opacity:0;">
<p>早在去年5月份，我们就和大家介绍过<a href="https://blog.laoda.de/archives/lobechat-ollama-deploy-offline">完全免费，离线可用！用LobeChat+Ollama搭建本地大模型</a></p>
<p>最近DeepSeek非常火，用的人太多，服务器负载过高，导致官方服务基本处于不可用状态……</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164348-1.webp&amp;size=m" alt="02ee23f435e7b3096085527c95dbe093.png"></p>
<p>既然DeepSeek是开源模型，那么，我们也来本地化部署一个。</p>
<h2 id="什么是-DeepSeek-R1--">什么是 DeepSeek-R1 ？</h2>
<p><code>DeepSeek-R1</code> 是 <code>DeepSeek</code> 的第一代推理模型，在数学、代码和推理任务中，其性能与 <code>OpenAI-o1</code> 相当（而OpenAI是闭源的），包括基于 <code>Llama</code> 和 <code>Qwen</code> 的六个从 <code>DeepSeek-R1</code> 蒸馏出的密集模型。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164347-1.webp&amp;size=m" alt="00a581dcb4954d59690969bbae044b28.png"></p>
<p>其中 <code>671b</code> 是<strong>教师模型</strong>（<code>Teacher Model</code>）， 另外的 <code>6</code> 个蒸馏模型为<strong>学生模型</strong>（<code>Student Model</code>）</p>
<ul>
 <li><code>1.5b</code>：全称是 <code>DeepSeek-R1-Distill-Qwen-1.5B</code>，蒸馏模型源自 <code>Qwen-2.5</code> 系列；</li>
 <li><code>7b</code>：是 <code>DeepSeek-R1-Distill-Qwen-7B</code>，蒸馏模型源自 <code>Qwen-2.5</code> 系列；</li>
 <li><code>8b</code>：是 <code>DeepSeek-R1-Distill-Llama-8B</code>，蒸馏模型源自 <code>Llama3.1-8B-Base</code>；</li>
 <li><code>14b</code>：是 <code>DeepSeek-R1-Distill-Qwen-14B</code>，蒸馏模型源自 <code>Qwen-2.5</code> 系列；</li>
 <li><code>32b</code>：是 <code>DeepSeek-R1-Distill-Qwen-32B</code>，蒸馏模型源自 <code>Qwen-2.5</code> 系列；</li>
 <li><code>70b</code>：是 <code>DeepSeek-R1-Distill-Llama-70B</code>，蒸馏模型源自 <code>Llama3.3-70B-Instruct</code>；</li>
 <li></li>
</ul>
<h3 id="什么是蒸馏--">什么是蒸馏 ？</h3>
<p>蒸馏技术（<code>Distillation</code>）是一种模型压缩和优化的方法，主要用于将一个大型、复杂的模型的知识转移到一个较小的模型中。这个过程通常被称为“知识蒸馏”（<code>Knowledge Distillation</code>）</p>
<h2 id="模型选择">模型选择</h2>
<p>我们需要根据硬件的性能以及实际的需求来选择不同参数大小的模型：</p>
<pre><code class="language-bash">ollama run deepseek-r1:1.5b
ollama run deepseek-r1:7b
ollama run deepseek-r1:8b
ollama run deepseek-r1:14b
</code></pre>
<p>没有配备专业级显卡的，推荐用14B以内的模型。</p>
<h3 id="deepseek-r1-1-5b">deepseek-r1:1.5b</h3>
<ul>
 <li>CPU: 任何现代CPU(10年内的型号)</li>
 <li>RAM: 最低8GB</li>
 <li>GPU: 不需要专用GPU</li>
 <li>存储: 至少20GB可用空间,推荐SSD</li>
</ul>
<p>这个模型对硬件要求最低,适合基础任务如简单写作和快速对话。</p>
<h3 id="deepseek-r1-7b">deepseek-r1:7b</h3>
<ul>
 <li>CPU: 4核或以上(如Intel i5/Ryzen 5)</li>
 <li>RAM: 至少16GB</li>
 <li>GPU: NVIDIA RTX 3070 8GB或更高</li>
 <li>存储: 至少20GB可用空间,推荐SSD</li>
</ul>
<p>适用于一般推理、较长文本生成和简单编码任务。</p>
<h3 id="deepseek-r1-8b">deepseek-r1:8b</h3>
<p>硬件要求与7b模型相近:</p>
<ul>
 <li>CPU: 4核或以上</li>
 <li>RAM: 至少16GB</li>
 <li>GPU: NVIDIA RTX 3070 8GB或更高</li>
 <li>存储: 至少20GB可用空间,推荐SSD</li>
</ul>
<h3 id="deepseek-r1-14b">deepseek-r1:14b</h3>
<ul>
 <li>CPU: 6核或以上(如Intel i7/Ryzen 7)</li>
 <li>RAM: 至少32GB</li>
 <li>GPU: NVIDIA RTX 3080 10GB或更高,推荐NVIDIA A4000 16GB</li>
 <li>存储: 至少20GB可用空间,推荐SSD</li>
</ul>
<p>这个模型适合更深入的推理、编码和研究任务。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164344-1.webp&amp;size=m" alt="342bc09e3bc5b249e4e9d502f27b73fa.png"></p>
<pre><code class="language-bash">ollama run deepseek-r1:32b
ollama run deepseek-r1:70b
ollama run deepseek-r1:671b
</code></pre>
<p>32b，70b，671b对机器的要求如下：</p>
<h3 id="DeepSeek-R1-Distill-Qwen-32B">DeepSeek-R1-Distill-Qwen-32B</h3>
<ul>
 <li>VRAM需求：约14.9GB</li>
 <li>推荐GPU配置：NVIDIA RTX 4090 24GB</li>
 <li>RAM：建议至少32GB</li>
</ul>
<h3 id="DeepSeek-R1-Distill-Llama-70B">DeepSeek-R1-Distill-Llama-70B</h3>
<ul>
 <li>VRAM需求：约32.7GB</li>
 <li>推荐GPU配置：NVIDIA RTX 4090 24GB × 2</li>
 <li>RAM：建议48GB以上</li>
</ul>
<h3 id="DeepSeek-R1-671B-完整模型-">DeepSeek-R1 671B（完整模型）</h3>
<ul>
 <li>VRAM需求：约1,342GB（使用FP16精度）</li>
 <li>推荐GPU配置：多GPU设置，例如NVIDIA A100 80GB × 16</li>
 <li>RAM：512GB以上</li>
 <li>存储：500GB以上高速SSD</li>
</ul>
<p>需要注意的是，对于671B模型：</p>
<ol>
 <li>通常需要企业级或数据中心级硬件来管理其巨大的内存和计算负载。</li>
 <li>使用量化技术可以显著降低VRAM需求。例如，使用4位量化后，模型大小可降至约404GB。</li>
 <li>使用动态量化技术，可以进一步降低硬件需求，将大部分参数量化到1.5-2.5位，使模型大小降至212GB-131GB之间。</li>
 <li>对于本地部署，可能需要考虑使用多台高性能工作站或服务器，如使用多个Mac Studio（M2 Ultra，192GB RAM）来满足内存需求。</li>
 <li>运行完整671B模型时，还需考虑功耗（可能高达10kW）和散热等问题。</li>
</ol>
<p>总的来说，32B和70B模型可以在高端消费级硬件上运行，而671B模型则需要企业级或数据中心级的硬件配置。选择合适的硬件配置时，还需考虑具体的使用场景、性能需求和预算限制。</p>
<p>咕咕的Mac配置如下：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164335-1.webp&amp;size=m" alt="836f64d6e995268a6690c78697ec445e.png" style="zoom:50%;">
<p>由于M系列MacBook采用统一内存架构，这意味着CPU和GPU可以共享同一内存池。这种设计减少了数据在不同处理单元之间传输的需要，从而可以显著提高大型数据集处理的速度和效率。</p>
<p>所以，理论上我可以在本地跑DeepSeek-R1-Distill-Qwen-32B，一会儿我们来试试！</p>
<h2 id="下载安装Ollama">下载安装Ollama</h2>
<p>官方网站：<a href="https://ollama.com/">https://ollama.com/</a></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164332-1.webp&amp;size=m" alt="67c46a3feb85d570a13fa6a242e9c380.png"></p>
<p>其实这个也可以用Docker来装，但是既然给了安装版，我们就直接到官网下载即可。</p>
<h3 id="什么是Ollama-">什么是Ollama？</h3>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164318-1.webp&amp;size=m" style="zoom:25%;">
<p>Ollama 是一个便于本地部署和运行大型语言模型（Large Language Models, LLMs）的工具。使用通俗的语言来说，如果你想在自己的电脑上运行如 GPT-3 这样的大型人工智能模型，而不是通过互联网连接到它们，那么 Ollama 是一个实现这一目标的工具。</p>
<p>Ollama支持非常多的开源模型，比如：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164315-1.webp&amp;size=m" alt="0bbb50a6f238e105966021293bd3bebf.png"></p>
<p>更多支持的模型可以看这边：<a href="https://ollama.com/library">https://ollama.com/library</a></p>
<p>当然它还支持自定义模型，这边就不深入了，有兴趣的可以研究：<a href="https://ollama.com/library">https://github.com/ollama/ollama</a></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164308-1.webp&amp;size=m" alt="0cf74812cbf4ff013672845d9c6a0519.png"></p>
<p>装好之后，直接像打开APP一样打开，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164307-1.webp&amp;size=m" alt="86acde18f586e7b7d7f706f46eef8447.png"></p>
<p>或者命令行运行:</p>
<pre><code class="language-bash">ollama -v
</code></pre>
<p>查看到版本号说明安装好了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164304-1.webp&amp;size=m" alt="d11b34a42dd77681401819a24a7694cc.png"></p>
<p>接下来我们下载一个<code>deepseek-r1:32b</code>的模型：(这边大家按照自己电脑的实际配置情况，结合上面不同参数模型对应的电脑配置来选择合适大小参数的模型进行安装)</p>
<pre><code class="language-bash">ollama run deepseek-r1:32b
</code></pre>
<p>这边可能需要比较长的时间，取决于你的网速。</p>
<p>下载好了就可以进行交互了：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164302-1.webp&amp;size=m" alt="0e828a1a0890afd72407268e2940436c.png"></p>
<p><code>/?</code> 可以查看帮助：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164301-1.webp&amp;size=m" alt="b4142aa5419da3cdad6f2a6657c150de.png"></p>
<p><code>/bye</code> 可以退出</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164259-1_1.webp&amp;size=m" alt="97bfe8935960d6cc3035cf3d8eea4afe.png"></p>
<p>我们来问几个其他问题。</p>
<p>在问问题之前，Ollama官方提供了计算推理速度的工具，只要在聊天窗口输入<code>/set verbose</code>就能使其在每次回复后自动输出运行速度。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164258-1.webp&amp;size=m" alt="16aa06a5e51369a5fa9ea834fc7dd911.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164258-1_1.webp&amp;size=m" alt="1f4780456d103c6741d96366bb002c17.png"></p>
<p>emm，换个问题，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164259-1.webp&amp;size=m" alt="46f3917da29819e92eb521e3f6930a82.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164252-1.webp&amp;size=m" alt="5fed27952279fa3e36debac5a1eeca0b.png"></p>
<p>8.34 tokens/s 还是基本一个可用的状态，</p>
<p>但是32B显然还是不够犀利，贴一个满血版本的回答：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164249-1.webp&amp;size=m" alt="1b19ba1dbaccce11b591627402aa51d2.png"></p>
<p>其实到这里，我们现在已经搞定了，你可以让它帮你干活了，但是每次都要用命令行，有些人觉得不方便，而且也不能给别人用，下面我们就给它搞一个图形化界面，扩展一下功能，也能让局域网里的其他小伙伴也用上你的这个模型（注意多人同时访问会导致机器负载飙升，具体取决于你机器的性能和模型参数的大小）</p>
<h2 id="安装浏览器插件--Page-Assist">安装浏览器插件——Page Assist</h2>
<p>除了在命令行里运行Ollama，我们可以使用一个名为<code>Page Assist</code>的浏览器插件，这款插件可以让我们能够在浏览器页面运行我们的本地大模型。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164240-1.webp&amp;size=m" alt="图片"></p>
<p>你可以通过<a href="https://chromewebstore.google.com/detail/page-assist-本地-ai-模型的-web/jfgfiigpkhlkbnfnbobbkinehhfdhndo?pli=1">访问Chrome插件链接</a>直接安装，</p>
<p>也可以通过 Page Assist的<a href="https://github.com/n4ze3m/page-assist">GitHub界面</a>所述的步骤进行安装。</p>
<p>安装好插件后，就可以设置下 Ollama 的模型，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164238-1.webp&amp;size=m" alt="图片"></p>
<p>设置好相应的地址后就可以保存了，这样就可以使用相应的模型进行问答了。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164235-1.webp&amp;size=m" alt="图片"></p>
<p>如果有很多的模型，也可以在管理模型中进行管理和添加。</p>
<p>为了更好的使用模型，我们也可以增加自己的知识库，在使用知识库之前需要进行RAG 设置。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164233-1.webp&amp;size=m" alt="图片"></p>
<p>我选择了<code>snowflake-arctic-embed2</code>的 embedded 模型，</p>
<pre><code class="language-bash">ollama pull snowflake-arctic-embed2
</code></pre>
<p>当然也可以选择推荐的模型，如果没有，可以到管理模型中添加。</p>
<p>完成后就可以通过管理知识进行知识库的添加。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164231-1.webp&amp;size=m" alt="图片"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164228-1.webp&amp;size=m" alt="图片"></p>
<p>然后就可以打开界面选择模型进行对话了。</p>
<p>Page Assist还有一些其他的功能，比如<code>管理知识</code>，<code>管理提示词</code>等等，大家可以自行研究一下，重要的是，现在我们使用起来更直观一些了！</p>
<h3 id="Page-Assist侧边栏功能">Page Assist侧边栏功能</h3>
<p>在任意一个网页，选中 <code>Page Assist</code> 插件点右键菜单，启动 <code>侧边栏</code></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164227-1.webp&amp;size=m" alt="a3de30d55729261e38cc25ba0a262b55.png"></p>
<p>勾选 <code>与当前页面聊天</code></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164225-1.webp&amp;size=m" alt="e9111755d8c8e59e287e757ba83a7640.png"></p>
<p>可以向模型提问，比如让模型总结一下页面的内容，</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164224-1.webp&amp;size=m" alt="edb51c66972bac5f895db03107ee6e41.png"></p>
<p>7B还是不够聪明，我们换32B再试试看：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164214-1.webp&amp;size=m" alt="86d06d581a6eefcefec8ea67aea238f0.png"></p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F164211-1.webp&amp;size=m" alt="bd5d798e2b3310904b84f364c81d9974.png"></p>
<p>这个效果就好多了。</p>
<p>好了，那就简单介绍这么多，有兴趣的小伙伴可以动手尝试起来了！</p>]]></description><guid isPermaLink="false">/archives/deploy-deepseek-r1-using-m1-max-macbook-pro</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F02%2F11%2F165314.webp&amp;size=m" type="image/jpeg" length="47398"/><category>有用的小知识</category><pubDate>Tue, 11 Feb 2025 08:52:06 GMT</pubDate></item><item><title><![CDATA[十分钟搭建一个跨平台剪贴板同步方案—— SyncClipboard！支持Windows/Linux/macOS/Android/IOS｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/cross-platform-cipboard-syncing-solution</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E5%8D%81%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%89%AA%E8%B4%B4%E6%9D%BF%E5%90%8C%E6%AD%A5%E6%96%B9%E6%A1%88%E2%80%94%E2%80%94%20SyncClipboard%EF%BC%81%E6%94%AF%E6%8C%81Windows%2FLinux%2FmacOS%2FAndroid%2FIOS%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/cross-platform-cipboard-syncing-solution" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>咕咕目前主要用的都是苹果生态的设备，登录了同一个Apple账号之后，是可以实现电脑复制，手机粘贴内容的，反之亦然。相信安卓也有类似的功能。</p>
<p>但是仍有不少小伙伴是安卓和苹果混用的，甚至是windows和Linux混用的，有没有一个方案可以也实现跨设备之间也粘贴同步呢？</p>
<p>今天介绍的SyncClipboard就是要实现这个功能的，感谢@chin的推荐。</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163804-1.webp&amp;size=m" alt="0b998795311aba59f660652a22c6b715.png"></p>
<h2 id="2--SyncClipboard主要功能-抄来自官方GitHub-">2. SyncClipboard主要功能（
 <del>抄</del>
 来自<a href="https://github.com/Jeric-X/SyncClipboard">官方GitHub</a>）</h2>
<ul>
 <li>剪贴板同步，支持文字、图片和文件。服务器/客户端架构，可以使用客户端内置服务器、独立部署服务器，也可以使用支持WebDAV的网盘作为服务器</li>
 <li>优化图片类型的剪贴板，功能有：
  <ul>
   <li>从任意位置复制图片时，可以直接向文件系统粘贴图片文件，反之亦然</li>
   <li>从浏览器复制图片后，后台下载原图到本地，解决无法从浏览器拷贝动态图的问题（大多网站有认证，适用范围有限，支持bilibili动态图片）</li>
   <li>从文件系统复制较新格式类型的图片文件时（webp/heic等），在剪贴板内储存gif或jpg格式，用于直接向支持图片的文本框粘贴图片</li>
  </ul></li>
</ul>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/Jeric-X/SyncClipboard">https://github.com/Jeric-X/SyncClipboard</a> (全新项目，目前1.9个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的<a href="https://loll.cc/tx">腾讯云轻量应用服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<p>当然你也可以选择不自己搭服务器用客户端内置服务器（可能有小伙伴担心隐私问题），或者是WebDAV服务器。</p>
<p>可以使用支持WebDAV协议的网盘作为服务器
 <br>
 测试过的服务器：</p>
<ul>
 <li><a href="https://nextcloud.com/">Nextcloud</a></li>
 <li><a href="https://alist.nn.ci/">AList</a></li>
 <li><a href="https://infini-cloud.net/en/">InfiniCLOUD</a></li>
 <li><a href="https://github.com/messense/aliyundrive-webdav">aliyundrive-webdav</a></li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：<a href="https://youtu.be/IR2FLA0skro">https://youtu.be/IR2FLA0skro</a></p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：<a href="https://www.bilibili.com/video/BV1RPwjewEks/">https://www.bilibili.com/video/BV1RPwjewEks/</a></p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/syncclipboard

cd /root/data/docker_data/syncclipboard
</code></pre>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  syncclipboard-server:
    image: jericx/syncclipboard-server:latest
    container_name: syncclipboard-server
    restart: unless-stopped
    ports:
      - "5133:5033" # 左边的5133可以改成服务器上没有用过的其他端口
    environment:
      - SYNCCLIPBOARD_USERNAME=这里改成你的英文的用户名
      - SYNCCLIPBOARD_PASSWORD=这个改成你的密码
</code></pre>
<p>其中的<code>5133</code>可以改成服务器上没有用过的端口，记得修改自己的用户名和密码，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>5133</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:5133  #查看 5133 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-syncclipboard">6.4 启动 syncclipboard</h3>
<pre><code>cd /root/data/docker_data/syncclipboard

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:5133</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！http使用明文传输太危险，我们部署在公网一定要考虑使用反向代理工具配置SSL！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153848-1.webp&amp;size=m" alt="c216b6334d5fd8bb16528cf45c847748.png" style="zoom:50%;">
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163757-1.webp&amp;size=m" alt="7eef63685004801654a7f233b02533e1.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163750-1.webp&amp;size=m" alt="4f93de5a64c13c0564ae9bf0109db512.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163746-1.webp&amp;size=m" alt="bd3a6dbf6e30ff0725245a923803febc.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163753-1.webp&amp;size=m" alt="8e7761cb295766fe8a9eef11f46acc04.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>5133</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 SyncClipboard 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 syncclipboard 所在的服务器 IP 就行。</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:5133/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<h3 id="8-1-登陆使用-以安卓和IOS为例子-">8.1 登陆使用（以安卓和IOS为例子）</h3>
<p>这边我手头没有window电脑，我演示一下安卓和IOS如何互通粘贴板。</p>
<h4 id="安卓配置">安卓配置</h4>
<p>安卓下载一个APP——HTTP Request Shortcuts</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163729-1.webp&amp;size=m" alt="b36576ad02aeb17ee170ef658b1f1850.png"></p>
<p>可以直接在谷歌应用商店搜索下载：https://play.google.com/store/apps/details?id=ch.rmy.android.http_shortcuts</p>
<p>也可以在F-Droid下载：https://f-droid.org/en/packages/ch.rmy.android.http_shortcuts/</p>
<p>或者直接GitHub上下载：https://github.com/Waboodoo/HTTP-Shortcuts/releases</p>
<p>HTTP Request Shortcuts的GitHub仓库：https://github.com/Waboodoo/HTTP-Shortcuts</p>
<p>手机上下载，导入这个<a href="https://github.com/Jeric-X/SyncClipboard/blob/master/script/shortcuts.zip">配置文件</a>，</p>
<p>这个是个压缩包，解压之后是个json文件，然后一会儿上传到HTTP Request Shortcuts里面即可。</p>
<p>不方便下载的，咕咕这边留一个网盘的地址，大家可以在这边下载：<a href="https://share.gugu.ovh/local/%E5%85%AC%E5%85%B1%E6%96%87%E4%BB%B6%E5%A4%B9/Docker%E9%A1%B9%E7%9B%AE/SyncClipboard">https://share.gugu.ovh/local/%E5%85%AC%E5%85%B1%E6%96%87%E4%BB%B6%E5%A4%B9/Docker%E9%A1%B9%E7%9B%AE/SyncClipboard</a></p>
<p>json的内容是这个：</p>
<pre><code class="language-json">{
  "categories": [
    {
      "id": "accb6a5b-60a3-4ba5-921a-f9cd772067aa",
      "name": "快捷方式",
      "shortcuts": [
        {
          "authentication": "basic",
          "bodyContent": "{\"File\":\"\",\"Clipboard\":\"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}\",\"Type\":\"Text\"}",
          "codeOnSuccess": "showToast(\u0027已上传\u0027);",
          "contentType": "application/json",
          "description": "支持选中文字后分享",
          "iconName": "freepik_upload",
          "id": "d6a958cb-3fa6-4c79-b342-229008bfac8a",
          "method": "PUT",
          "name": "上传剪贴板",
          "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
          "proxy": "",
          "quickSettingsTileShortcut": true,
          "responseHandling": {
            "successOutput": "none"
          },
          "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
          "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
        },
        {
          "authentication": "basic",
          "codeOnSuccess": "const profile \u003d JSON.parse(response.body)\r\nconst type \u003d profile.Type\r\n\r\nif (type \u003d\u003d \u0027Text\u0027) {\r\n    const ClibboardText \u003d profile.Clipboard;\r\n    copyToClipboard(ClibboardText);\r\n    showToast(\u0027已拷贝\\n\u0027 + ClibboardText);\r\n\r\n    const httpstr \u003d httpString(ClibboardText);\r\n\r\n    if (httpstr) {\r\n        if (confirm(\u0027包含网址，是否打开\u0027)) {\r\n            openUrl(httpstr[0]);\r\n        }\r\n    }\r\n}\r\nelse if (profile.File \u0026\u0026 profile.File.length \u003e 0) {\r\n    const downloadUrl \u003d getVariable(/*[variable]*/\"136751b5-5f38-49fc-81dc-80a825804203\"/*[/variable]*/) + \u0027/file/\u0027 + encodeURIComponent(profile.File)\r\n    const inputPara \u003d { \u0027downloadUrl\u0027: downloadUrl }\r\n    showToast(\u0027文件名已拷贝，正在下载\\n\u0027 + profile.File)\r\n    copyToClipboard(profile.File)\r\n    if (type \u003d\u003d \u0027Image\u0027 || isImageFile(profile.File)) {\r\n        enqueueShortcut(/*[shortcut]*/\"1e693964-ab59-4e9c-902b-6b94b90ff2f0\"/*[/shortcut]*/, inputPara)\r\n    } else {\r\n        enqueueShortcut(/*[shortcut]*/\"1e693964-ab59-4e9c-902b-6b94b90ff2f0\"/*[/shortcut]*/, inputPara)\r\n    }\r\n}\r\n\r\nfunction isImageFile(file) {\r\n    const filename \u003d file.toLowerCase();\r\n    const list \u003d [\r\n        \u0027.png\u0027,\r\n        \u0027.jpg\u0027,\r\n        \u0027.jpeg\u0027,\r\n        \u0027.gif\u0027,\r\n        \u0027.bmp\u0027,\r\n        \u0027.webp\u0027,\r\n    ]\r\n    let result \u003d false\r\n    list.forEach(element \u003d\u003e {\r\n        if (filename.endsWith(element)) {\r\n            result \u003d true\r\n        }\r\n    })\r\n    return result\r\n}\r\n\r\nfunction httpString(s) {\r\n    var reg \u003d /(https?|http|ftp|file):\\/\\/[-A-Za-z0-9+\u0026@#/%?\u003d~_|!:,.;]+[-A-Za-z0-9+\u0026@#/%\u003d~_|]/g;\r\n    s \u003d s.match(reg);\r\n    return (s)\r\n}",
          "iconName": "freepik_download",
          "id": "91cf41c5-da0c-45b5-988c-9f636e135abd",
          "name": "下载剪贴板",
          "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
          "proxy": "",
          "quickSettingsTileShortcut": true,
          "responseHandling": {
            "successOutput": "none"
          },
          "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
          "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
        },
        {
          "authentication": "basic",
          "bodyContent": "{\"File\":\"\",\"Clipboard\":\"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}\",\"Type\":\"Text\"}",
          "codeOnPrepare": "setVariable(/*[variable]*/\"d12cab01-6d2b-44aa-a1fb-dfddc6fe7895\"/*[/variable]*/, selectedFiles[0].name);",
          "codeOnSuccess": "enqueueShortcut(\u0027上传文件 控制部分\u0027)",
          "contentType": "application/json",
          "description": "从分享菜单使用",
          "iconName": "freepik_upload",
          "id": "2b8e95a4-2ece-41a1-aace-f8f80c0497fb",
          "method": "PUT",
          "name": "上传文件",
          "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
          "proxy": "",
          "requestBodyType": "file",
          "responseHandling": {
            "successOutput": "none"
          },
          "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/file/{{d12cab01-6d2b-44aa-a1fb-dfddc6fe7895}}",
          "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
        }
      ]
    },
    {
      "id": "316553f3-4bb0-4e10-806b-0de26e10fb2a",
      "name": "基础组件",
      "shortcutClickBehavior": "edit",
      "shortcuts": [
        {
          "authentication": "basic",
          "bodyContent": "{\"File\":\"{{d12cab01-6d2b-44aa-a1fb-dfddc6fe7895}}\",\"Clipboard\":\"\",\"Type\":\"File\"}",
          "codeOnSuccess": "showToast(\u0027已上传\u0027);",
          "contentType": "application/json",
          "iconName": "freepik_upload",
          "id": "2424dcac-6fa0-4ff9-849b-63a56d63c79f",
          "method": "PUT",
          "name": "上传文件 控制部分",
          "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
          "proxy": "",
          "responseHandling": {
            "successOutput": "none"
          },
          "url": "{{136751b5-5f38-49fc-81dc-80a825804203}}/SyncClipboard.json",
          "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
        },
        {
          "authentication": "basic",
          "bodyContent": "{\"File\":\"\",\"Clipboard\":\"{{76b1e948-84b3-497e-8ec5-b911d00f8f0f}}\",\"Type\":\"Text\"}",
          "contentType": "application/json",
          "description": "只支持2m以下文件",
          "iconName": "flat_color_folder",
          "id": "1e693964-ab59-4e9c-902b-6b94b90ff2f0",
          "name": "展示文件",
          "password": "{{9421719b-086f-4799-8432-158b84b6e05a}}",
          "proxy": "",
          "requestBodyType": "file",
          "responseHandling": {
            "actions": [
              "share",
              "copy",
              "save"
            ]
          },
          "url": "{{5989c421-2669-4424-80c3-69ba7995524a}}",
          "username": "{{719f997c-6bf6-458f-a148-3c2a8ac5e405}}"
        }
      ]
    }
  ],
  "compatibilityVersion": 71,
  "variables": [
    {
      "id": "719f997c-6bf6-458f-a148-3c2a8ac5e405",
      "key": "UserName",
      "value": "ChangeIt"
    },
    {
      "id": "9421719b-086f-4799-8432-158b84b6e05a",
      "key": "UserToken",
      "value": "ChangeIt"
    },
    {
      "flags": 1,
      "id": "76b1e948-84b3-497e-8ec5-b911d00f8f0f",
      "jsonEncode": true,
      "key": "Clipboard",
      "type": "clipboard"
    },
    {
      "id": "d12cab01-6d2b-44aa-a1fb-dfddc6fe7895",
      "jsonEncode": true,
      "key": "FileName",
      "value": ""
    },
    {
      "id": "136751b5-5f38-49fc-81dc-80a825804203",
      "key": "url",
      "value": "ChangeIt"
    },
    {
      "id": "5989c421-2669-4424-80c3-69ba7995524a",
      "key": "downloadUrl",
      "value": ""
    }
  ],
  "version": 75
}
</code></pre>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163722-1.webp&amp;size=m" alt="d4b17dd5bd294d8244940b4418e8e2fb.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163713-1.webp&amp;size=m" alt="750f75c37d12dd1a680e9ae317f7091a.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163703-1.webp&amp;size=m" alt="14172fe7c5ab7b2ad09de74657977bbe.png" style="zoom:50%;">
<p>修改<code>变量</code>中的<code>UserName</code>，<code>UserToken</code>，<code>url</code>， <code>url</code>不要以斜线分隔符<code>/</code>结尾。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163659-1.webp&amp;size=m" alt="7261d6c48868fb4e26ac61c8405a4c2d.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163655-1.webp&amp;size=m" alt="55c0314a6dade811b56aca4e2ec20af5.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163653-1.webp&amp;size=m" alt="b21a1ee5a7bd3fc83e0ca0889e2223ae.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163648-1.webp&amp;size=m" alt="ffd4fba54810115f517b1edd83742b54.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163652-1.webp&amp;size=m" alt="9b826c51f2a2f256b0f5821c9c5f2190.png" style="zoom:50%;">
<p><code>HTTP Request Shortcuts</code>支持从下拉菜单、桌面组件、桌面图标、分享菜单中使用。</p>
<h4 id="IOS配置">IOS配置</h4>
<p>官方给了很多选择：</p>
<p>使用<a href="https://apps.apple.com/cn/app/快捷指令/id1462947752">快捷指令</a></p>
<ul>
 <li>手动同步，导入这个<a href="https://www.icloud.com/shortcuts/ecd4200276ba4cc2b0839462215eb1d8">快捷指令</a>，手动触发上传或下载</li>
 <li>自动同步，导入这个<a href="https://www.icloud.com/shortcuts/542ad23b33314b36807c05a5d8aa5c22">快捷指令</a>，运行后设备会自动在后台同步剪贴板内容，此快捷指令将执行无限时长，需要手动关闭，你还可以手动修改同步后是否发送系统通知、查询的间隔秒数</li>
 <li>自动上传短信验证码，参考这个帖子中的视频教程 <a href="https://github.com/Jeric-X/SyncClipboard/discussions/60">#60</a></li>
</ul>
<p>我自己偏向于手动同步，所以导入了这个<a href="https://www.icloud.com/shortcuts/ecd4200276ba4cc2b0839462215eb1d8">快捷指令</a>，手动触发上传或下载。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163628-1.webp&amp;size=m" alt="IMG_5563.jpg" style="zoom:50%;">
<p>记得修改一下这三个，</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F14%2F163623-1.webp&amp;size=m" alt="IMG_5564.jpg" style="zoom:50%;">
<p>然后保持就可以了。</p>
<p>试试效果吧！亲测非常好用！</p>
<p>WIndows, Linux, macOS客户端，Arch Linux还有其他安卓的方式，大家可以参考官方的文档：<a href="https://github.com/Jeric-X/SyncClipboard">https://github.com/Jeric-X/SyncClipboard</a></p>
<p>为了避免有些小伙伴访问不了，我也粘贴一份在博客里：</p>
<p>桌面客户端（Windows/Linux/macOS）运行在后台时将自动同步剪贴板</p>
<h4 id="Windows">Windows</h4>
<p>下载地址：<a href="https://github.com/Jeric-X/SyncClipboard/releases/">Release</a>页面中的<code>SyncClipboard.zip</code>，解压缩后运行<code>SyncClipboard.exe</code></p>
<p>依赖：</p>
<ul>
 <li><a href="https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-6.0.16-windows-x64-installer">.NET 6.0桌面运行时</a>，未安装会弹窗提醒并跳转到微软官方下载页面</li>
 <li><a href="https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-aspnetcore-6.0.16-windows-x64-installer">ASP.NET Core 6.0运行时</a>，未安装会弹窗提醒并跳转到微软官方下载页面</li>
 <li>Windows10 2004及以上</li>
 <li>微软<a href="https://learn.microsoft.com/zh-cn/windows/apps/design/style/segoe-fluent-icons-font">Segoe Fluent Icons</a>图标字体，Windows11自带无需安装，Windows10需要手动下载安装（<a href="https://aka.ms/SegoeFluentIcons">官方地址</a>），否则界面图标会大范围出错</li>
</ul>
<p>注意：</p>
<ul>
 <li>删除软件时，配置文件目录不会被删除，配置文件储存在<code>%AppData%\SyncClipboard\</code>，需要彻底删除软件时请手动删除整个目录</li>
</ul>
<h4 id="Linux--macOS">Linux, macOS</h4>
<p>下载地址：<a href="https://github.com/Jeric-X/SyncClipboard.Desktop/releases">SyncClipboard.Desktop</a>，根据系统选择你需要的安装包</p>
<p>注意：</p>
<ul>
 <li>名称中带有<code>no-self-contained</code>：依赖<a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0">.NET 6.0桌面运行时</a>和<a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0">ASP.NET Core 6.0运行时</a></li>
 <li>名称中带有<code>self-contained</code>：通常可以直接运行</li>
 <li>删除软件时，配置文件目录不会被删除，配置文件储存在<code>~/.config/SyncClipboard/</code>(Linux)，<code>~/Library/Application Support/SyncClipboard/</code>(macOS)，需要彻底删除软件时请手动删除整个目录</li>
 <li>使用<code>deb</code>、<code>rpm</code>安装包时，每次更新版本需要先删除旧版，再安装新版，不支持直接更新</li>
 <li>Linux: 快捷键在Wayland不可用</li>
 <li>Linux: 无法自动识别语言，默认为英语</li>
 <li>macOS: <code>“SyncClipboard”已损坏，无法打开</code>，在终端中执行<code>sudo xattr -d com.apple.quarantine /Applications/SyncClipboard.app</code></li>
 <li>macOS: 快捷键依赖辅助功能权限(Accessibility)，软件在需要时会弹窗提示（所有快捷键为空时则不需要），每个新版本需要重新授予权限</li>
</ul>
<h4 id="Arch-Linux">Arch Linux</h4>
<p>Arch Linux 用户可以直接从 <a href="https://aur.archlinux.org/packages/syncclipboard-desktop">AUR</a> 安装：</p>
<pre><code>paru -Sy syncclipboard-desktop
</code></pre>
<p>安装后从菜单中启动即可，如果要从命令行中启动，请注意需要英文环境，即以 <code>LANG=en_US.UTF-8 syncclipboard-desktop</code> 来启动，启动后可以在软件内设置语言为中文。配置保存路径为：<code>~/.config/SyncClipboard</code>。</p>
<h4 id="Android">Android</h4>
<h5 id="使用HTTP-Request-Shortcuts">使用<a href="https://github.com/Waboodoo/HTTP-Shortcuts">HTTP Request Shortcuts</a></h5>
<p>导入这个<a href="https://github.com/Jeric-X/SyncClipboard/blob/master/script/shortcuts.zip">配置文件</a>，修改<code>变量</code>中的<code>UserName</code>，<code>UserToken</code>，<code>url</code>， <code>url</code>不要以斜线分隔符<code>/</code>结尾。<code>HTTP Request Shortcuts</code>支持从下拉菜单、桌面组件、桌面图标、分享菜单中使用</p>
<h5 id="使用Autox-js">使用<a href="https://github.com/kkevsekk1/AutoX">Autox.js</a></h5>
<ul>
 <li>自动同步，使用这个<a href="https://github.com/Jeric-X/SyncClipboard/blob/master/script/SyncAutoxJs.js">js文件</a>。由于安卓系统限制，在安卓10及以上的系统应用无法在后台读取剪贴板，但可以使用基于Root权限的工具(Magisk/Xposed)解除应用后台读取剪贴版的权限，如<a href="https://github.com/Kr328/Riru-ClipboardWhitelist">Riru-ClipboardWhitelist</a>、<a href="https://modules.lsposed.org/module/io.github.tehcneko.clipboardwhitelist">Clipboard Whitelist</a>。由于在安卓13及以上的系统应用必须由用户手动授权才被允许访问系统日志（剪贴板），也可以使用Xposed自动为应用授权访问系统日志的权限，如<a href="https://github.com/QueallyTech/DisableLogRequest">DisableLogRequest/禁用日志访问请求</a></li>
 <li>自动上传验证码，使用这个<a href="https://github.com/Jeric-X/SyncClipboard/blob/master/script/UploadVerificationCode.js">js文件</a>，这个脚本运行在后台时将读取所有通知消息，在识别到验证码类信息时将证码上传到服务器</li>
</ul>
<p>导入js文件、修改每个文件头部的用户配置后，手动点击运行，或者为每个js文件设置触发方式，例如：开机时触发</p>
<h5 id="使用SmsForwarder">使用<a href="https://github.com/pppscn/SmsForwarder">SmsForwarder</a></h5>
<ul>
 <li>自动上传验证码， <a href="https://github.com/Jeric-X/SyncClipboard/discussions/109">#109</a></li>
</ul>
<h5 id="使用Tasker">使用<a href="https://tasker.joaoapps.com/">Tasker</a></h5>
<ul>
 <li>https://github.com/forrestgao/taskerforSyncClipboard ，作者：<a href="https://github.com/forrestgao">forrestgao</a></li>
</ul>
<p>Tasker是一款安卓系统上非常强大的自动化工具软件，你可以根据SyncClipboard的API创建适合自己的配置文件，如果你认为你的配置文件非常通用并希望分享出来，欢迎联系我置于此处</p>
<h4 id="客户端配置说明">客户端配置说明</h4>
<p>全平台依赖三条必要配置（配置的拼写可能会有所不同，含义相同）。</p>
<ul>
 <li>user</li>
 <li>password</li>
 <li>url，格式为http(s)://ip(或者域名):port。使用WebDav服务器时，url需要具体到一个已存在的文件夹作为工作目录，例如<code>https://domain.com/dav/folder1/working%20folder</code>，特殊符号需要使用url转义字符代替，不要使用这个文件夹存储其他文件。不使用桌面客户端（Windows/Linux/macOS）时需在工作目录中再创建<code>file</code>文件夹以同步文件，桌面客户端会在设置服务器时自动创建<code>file</code>文件夹。url尽量不要以斜线分隔符<code>/</code>结尾，在部分客户端中会出现问题。</li>
</ul>
<h4 id="API">API</h4>
<p>API基于WebDAV，在独立服务器运行环境下设定环境变量ASPNETCORE_ENVIRONMENT为Development后运行服务器，或桌面客户端打开服务器并打开设置里的诊断模式后， 访问<code>http://ip:端口/swagger/index.html</code>可以打开API页面，以下是部分关键API</p>
<h4 id="获取-上传剪贴板-文字-">获取/上传剪贴板（文字）</h4>
<pre><code>GET /SyncClipboard.json
PUT /SyncClipboard.json
</code></pre>
<h4 id="获取-上传剪贴板-图片-文件-">获取/上传剪贴板（图片/文件）</h4>
<pre><code>GET  /SyncClipboard.json
HEAD /file/filename         // optional
GET  /file/filename

PUT /file/filename
PUT /SyncClipboard.json
</code></pre>
<h4 id="SyncClipboard-json">SyncClipboard.json</h4>
<pre><code>{
    "Type" : "Text"
    "Clipboard" : "Content",
    "File":""
}

{
    "Type": "Image", // or "File", "Group"
    "Clipboard": "hash, optional",
    "File": "filename"
}
</code></pre>
<h3 id="8-2-更新-SyncClipboard">8.2 更新 SyncClipboard</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/syncclipboard

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-3-卸载-SyncClipboard">8.3 卸载 SyncClipboard</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/syncclipboard

docker compose down

cd ..

rm -rf /root/data/docker_data/syncclipboard  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>目前暂时没啥问题，大家有问题欢迎评论区交流。</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/Jeric-X/SyncClipboard/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/Jeric-X/SyncClipboard">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢开发人员们的辛苦付出，让我们能用到这么优秀的项目！</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/Jeric-X/SyncClipboard">https://github.com/Jeric-X/SyncClipboard</a></p>]]></description><guid isPermaLink="false">/archives/cross-platform-cipboard-syncing-solution</guid><dc:creator>咕咕</dc:creator><enclosure url="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2025%2F01%2F16%2F210223.webp&amp;size=m" type="image/jpeg" length="51900"/><category>Docker系列</category><pubDate>Tue, 14 Jan 2025 08:43:05 GMT</pubDate></item><item><title><![CDATA[更适合新手的 AI 口语对话练习应用—— BabelDuck ｜好玩儿的Docker项目]]></title><link>https://blog.laoda.de/archives/docker-compose-install-babelduck</link><description><![CDATA[<img src="https://blog.laoda.de/plugins/feed/assets/telemetry.gif?title=%E6%9B%B4%E9%80%82%E5%90%88%E6%96%B0%E6%89%8B%E7%9A%84%20AI%20%E5%8F%A3%E8%AF%AD%E5%AF%B9%E8%AF%9D%E7%BB%83%E4%B9%A0%E5%BA%94%E7%94%A8%E2%80%94%E2%80%94%20BabelDuck%20%EF%BD%9C%E5%A5%BD%E7%8E%A9%E5%84%BF%E7%9A%84Docker%E9%A1%B9%E7%9B%AE&amp;url=/archives/docker-compose-install-babelduck" width="1" height="1" alt="" style="opacity:0;">
<h2 id="1--唠嗑">1. 唠嗑</h2>
<p>随着国际形势的发展，英语的重要性越来越高，（比如开个美卡遇到问题和客服沟通都有问题）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142644-1.webp&amp;size=m" alt="9d10fb90cb19adec54c01a40da0c73f5.png" style="zoom: 50%;">
<p>听读能力我们普遍比较强，薄弱的往往是说写能力，而其中的”写“现在又可以用GPT来辅助了，所以这一期我们就来分享一个提高英语的“说“的能力的小工具——BabelDuck。</p>
<p>BabelDuck是一个面向各水平层次语言学习者的高度可定制化 AI 口语对话练习应用，并对初学者更友好，旨在将口语表达练习的门槛与心智负担降至最低。</p>
<h2 id="2--babelduck主要功能-抄来自官方GitHub-">2. babelduck主要功能（
 <del>抄</del>
 来自<a href="https://github.com/Orenoid/BabelDuck">官方GitHub</a>）</h2>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142711-1.webp&amp;size=m" alt="7d958bd9ae6bdcc4836cc2ca17ab2a1d.png"></p>
<ul>
 <li>支持多对话管理、自定义系统提示词、流式响应等常见 AI 对话功能</li>
 <li>可在不影响当前对话的前提下，向 AI 寻求语法、翻译或表达润色等建议，并提供可定制化的快捷指令</li>
 <li>在对 AI 提供的建议有疑问时，可开启子对话进一步讨论，讨论结束后可无缝返回原对话</li>
 <li>支持语音输入与语音输出，集成了浏览器内置文本转语音 以及 Azure TTS</li>
 <li>集成多种 LLM AI 服务，支持自定义第三方 API 服务，可无缝切换（目前只支持OpenAI的API）</li>
 <li>数据存储于本地，确保用户数据隐私安全</li>
 <li>支持针对不同对话进行单独的偏好设置</li>
 <li>提供多语言界面</li>
 <li>内置使用教程</li>
 <li>支持Docker部署，更新维护方便</li>
</ul>
<h3 id="--未来规划">🎯 未来规划</h3>
<ul>
 <li>对话模板</li>
 <li>复述练习模式</li>
 <li>移动端适配</li>
 <li>语音回放</li>
 <li>支持多模态语音</li>
 <li>接入更多 LLM/TTS/STT 服务</li>
 <li>实时语音模式</li>
 <li>更多指令类型</li>
 <li>插件系统</li>
</ul>
<h2 id="3--相关地址">3. 相关地址</h2>
<p>官方GitHub地址：<a href="https://github.com/Orenoid/BabelDuck">https://github.com/Orenoid/BabelDuck</a> (全新项目，目前188个star，欢迎大家去给项目点星星！）</p>
<h2 id="4--搭建环境">4. 搭建环境</h2>
<ul>
 <li>服务器：咕咕这边用的<a href="https://gao.ee/lca">莱卡云香港服务器</a>，建议服务器内存1G以上，当然你也可以选择其他<a href="https://blog.laoda.de/vps">高性价比的服务器</a>。</li>
 <li>系统：Debian 11 （<a href="https://blog.laoda.de/archives/useful-script/">DD 脚本</a> 非必需 DD，用原来的系统也 OK，之后教程都是用 Debian 或者 Ubuntu 搭建～）</li>
 <li>安装好 Docker、Docker-compose（<a href="https://blog.laoda.de/archives/hello-docker/">相关脚本</a>）</li>
 <li>【必需】域名一枚，并做好解析到服务器上（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>）</li>
 <li>【非必需】提前安装好宝塔面板海外版本 aapanel，并安装好 Nginx（<a href="https://forum.aapanel.com/d/9-aapanel-linux-panel-6812-installation-tutorial">安装地址</a>）</li>
 <li>【非必需本教程选用】安装好 Nginx Proxy Manager（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>）</li>
</ul>
<h2 id="5--搭建视频-过俩天补充-----">5. 搭建视频（过俩天补充 = =）</h2>
<h3 id="5-1-YouTube">5.1 YouTube</h3>
<p>视频地址：</p>
<h3 id="5-2-哔哩哔哩">5.2 哔哩哔哩</h3>
<p>哔哩哔哩：</p>
<h2 id="6--搭建方式">6. 搭建方式</h2>
<h3 id="6-1-安装-Docker-与-Nginx-Proxy-Manager">6.1 安装 Docker 与 Nginx Proxy Manager</h3>
<p>可以直接参考这篇内容：</p>
<p><a href="https://blog.laoda.de/archives/nginxproxymanager/">https://blog.laoda.de/archives/nginxproxymanager/</a></p>
<h3 id="6-2-创建安装目录">6.2 创建安装目录</h3>
<p>创建一下安装的目录：</p>
<pre><code class="language-bash">sudo -i

mkdir -p /root/data/docker_data/babelduck

cd /root/data/docker_data/babelduck
</code></pre>
<p>接着我们来编辑下<code>env</code>文件</p>
<pre><code class="language-bash">vim .env
</code></pre>
<p>输入下面的内容：</p>
<pre><code class="language-yaml"># unforunately, the implementation of input handlers is coupled with openai at this time,
# so openai or openai-compatible services are necessary here (json mode required), once we decouple it from openai (working on it), we can remove this
OPENAI_CHAT_COMPLETION_URL=
OPENAI_API_KEY=
OPENAI_MODEL_NAME=

# another unfortunate thing is that the stt feature is coupled with siliconflow for now,
# so we need to provide the api url and api key as well, you can get the key from https://cloud.siliconflow.cn/account/ak
# Also, once we decouple it from siliconflow (which has been on the roadmap), we can remove these two variables
STT_API_URL=https://api.siliconflow.cn/v1/audio/transcriptions
SILICONFLOW_API_KEY=
</code></pre>
<p>这边可以选择填入相应的API和模型，也可以选择直接保存退出，这样的话，后续在网页端自己填写相关API密钥，适合分享给其他人用。</p>
<p>我们这边就不填，一会儿去网页端填写。</p>
<p>接着我们来编辑下<code>docker-compose.yml</code></p>
<pre><code class="language-bash">vim docker-compose.yml
</code></pre>
<pre><code class="language-yaml">services:
  babel-duck:
    image: orenoid/babel-duck:latest
    container_name: babel-duck
    env_file:
      - .env
    ports:
      - "9001:9000"
    restart: unless-stopped
</code></pre>
<p>其中的<code>9001</code>可以改成服务器上没有用过的端口，修改完成之后，可以在英文输入法下，按 <code>i</code> 修改，完成之后，按一下 <code>esc</code>，然后 <code>:wq</code> 保存退出。</p>
<h3 id="6-3-查看端口是否被占用">6.3 查看端口是否被占用</h3>
<p>查看端口是否被占用（以 <code>9001</code> 为例），输入：</p>
<pre><code class="language-bash">lsof -i:9001  #查看 9001 端口是否被占用，如果被占用，重新自定义一个端口
</code></pre>
<p>如果啥也没出现，表示端口未被占用，我们可以继续下面的操作了～</p>
<p>如果出现：</p>
<pre><code class="language-bash">-bash: lsof: command not found
</code></pre>
<p>运行：</p>
<pre><code class="language-bash">apt install lsof  #安装 lsof
</code></pre>
<p>如果端口没有被占用（被占用了就修改一下端口，比如改成 <code>8381</code>，注意 docker 命令行里和防火墙都要改）</p>
<h3 id="6-4-启动-babelduck">6.4 启动 babelduck</h3>
<pre><code>cd /root/data/docker_data/babelduck

docker compose up -d   # 注意，老版本用户用 docker-compose up -d
</code></pre>
<p>耐心等待拉取好镜像，出现 <code>done</code>的字样之后，</p>
<p>理论上我们就可以输入 <code>http://ip:9001</code> 访问了。</p>
<p>但是这边这个服务必须先搞一下反向代理！不然会报错！</p>
<p>做反向代理前，你需要一个域名！</p>
<p><a href="https://loll.cc/ns">namesilo</a> 上面 xyz 后缀的域名一年就 7 块钱，可以年抛。（冷知识，namesilo上 6位数字的xyz续费永远都是0.99美元 = =）</p>
<p>如果想要长期使用，还是建议买 com 后缀的域名，更加正规一些，可以输入 <code>laodade</code> 来获得 1 美元的优惠（不知道现在还有没有）</p>
<p><a href="https://loll.cc/ns">namesilo</a> 自带隐私保护，咕咕一直在用这家，价格也是这些注册商里面比较低的，关键是他家不像其他家域名注册商，没有七七八八的套路！（就是后台界面有些
 <del>丑</del>
 古老 = =）</p>
<p><a href="https://blog.laoda.de/archives/namesilo/">【域名购买】Namesilo 优惠码和域名解析教程（附带服务器购买推荐和注意事项）</a></p>
<p>我们接着往下看！</p>
<h2 id="7--反向代理">7. 反向代理</h2>
<h3 id="7-1-利用-Nginx-Proxy-Manager">7.1 利用 Nginx Proxy Manager</h3>
<p>在添加反向代理之前，确保你已经完成了域名解析，不会的可以看这个：<strong>域名一枚，并做好解析到服务器上</strong>（<a href="https://blog.laoda.de/archives/namesilo/">域名购买、域名解析</a> <a href="https://www.bilibili.com/video/BV1Sy4y1k7kZ/">视频教程</a>） （名称改成你自己想要的域名前缀即可）</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153848-1.webp&amp;size=m" alt="c216b6334d5fd8bb16528cf45c847748.png" style="zoom:50%;">
<p>之后，登陆 Nginx Proxy Manager（不会的看这个：<strong>安装 Nginx Proxy Manager</strong>（<a href="https://blog.laoda.de/archives/nginxproxymanager/">相关教程</a>））</p>
<blockquote>
 <p><strong>注意：</strong></p>
 <p>Nginx Proxy Manager（以下简称 NPM）会用到 <code>80</code>、<code>443</code> 端口，所以本机不能占用（比如原来就有 Nginx）</p>
</blockquote>
<p>直接丢几张图：</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142629-1.webp&amp;size=m" alt="54e5117d7800d0b5cc27220272a898e0.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142624-1.webp&amp;size=m" alt="3ebc270b46aec8fdea7b9b18c3950183.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142620-1.webp&amp;size=m" alt="56eba66aececc934819fc50faaf19013.png" style="zoom:50%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142615-1.webp&amp;size=m" alt="d1c972544ec24c3b4862521cc52a46ae.png" style="zoom:50%;">
<blockquote>
 <p>注意填写对应的 <code>域名</code>、<code>IP</code> 和 <code>端口</code>，按文章来的话，应该是 <code>9001</code></p>
</blockquote>
<p><strong>IP 填写：</strong></p>
<p>如果 Nginx Proxy Manager 和 babelduck 在同一台服务器上，可以在终端输入：</p>
<pre><code class="language-bash">ip addr show docker0
</code></pre>
<p>查看对应的 Docker 容器内部 IP。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153819-1.webp&amp;size=m" style="zoom:50%;">
<p>否则直接填 babelduck 所在的服务器 IP 就行。</p>
<h3 id="7-2-利用宝塔面板">7.2 利用宝塔面板</h3>
<p>发现还是有不少小伙伴习惯用宝塔面板，这边也贴一个宝塔面板的反代配置：</p>
<p>直接新建一个站点，不要数据库，不要 php，纯静态即可。</p>
<p>然后打开下面的配置，修改 Nginx 的配置。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153816-1.webp&amp;size=m" alt="image-20220819150345725" style="zoom: 33%;"> <img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153814-1.webp&amp;size=m" alt="image-20220819150542867" style="zoom: 33%;">
<p>代码如下：</p>
<pre><code class="language-nginx">location / {
      proxy_pass http://127.0.0.1:9001/;       # 注意改成你实际使用的端口
      rewrite ^/(.*)$ /$1 break;
      proxy_redirect off;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade-Insecure-Requests 1;
      proxy_set_header X-Forwarded-Proto https;
    }
</code></pre>
<p>此方法对 90% 的反向代理都能生效，然后就可以用域名来安装访问了。</p>
<p>有同学可能会问，为什么不直接用宝塔自带的反向代理功能。</p>
<img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F12%2F153804-1.webp&amp;size=m" alt="image-20220819150730128" style="zoom: 33%;">
<p>也可以，不过咕咕自己之前遇到过当有多个网站需要反代的时候，在这边设置会报错的情况 = =</p>
<p>所以后来就不用了，直接用上面的方法来操作了。</p>
<h2 id="8--使用教程">8. 使用教程</h2>
<h3 id="8-1-登陆使用">8.1 登陆使用</h3>
<p>见视频或者自己摸索下 = =</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142529-1.webp&amp;size=m" alt="9b59fdc57dcf2964a9c82237b5fd41a9.png"></p>
<p>这边logo裂开了......</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142527-1.webp&amp;size=m" alt="73566996569fca80012c46d599b08864.png"></p>
<p>设置页面：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142526-1.webp&amp;size=m" alt="04a5dcef0e0f2d579cfe266f15d09163.png"></p>
<p>语音可以用浏览器内置TTS：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142518-1.webp&amp;size=m" alt="7f7669d6028f55770447dc9d0827be0a.png"></p>
<p>模型这边，可以填入自己的OpenAI API Key：</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142513-1.webp&amp;size=m" alt="68d8309cfe60b9b26cf895c9ffc30ff3.png"></p>
<p>赶紧试试吧！</p>
<p><img src="https://blog.laoda.de/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fimg.laoda.de%2Fi%2F2024%2F12%2F17%2F142512-1.webp&amp;size=m" alt="61150cc48aef9a1388b29228baabe0dc.png"></p>
<h3 id="8-2-更新-babelduck">8.2 更新 babelduck</h3>
<p>这个项目后续应该也会有更新，所以提供一个更新的方式。</p>
<pre><code class="language-yaml">cd /root/data/docker_data/babelduck

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器，因为这么做需要额外的时间等待容器停止；docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器，完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像
</code></pre>
<p>提示：</p>
<pre><code class="language-bash">WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]
</code></pre>
<p>输入 <code>y</code></p>
<p>利用 Docker 搭建的应用，更新非常容易～</p>
<h3 id="8-3-卸载-babelduck">8.3 卸载 babelduck</h3>
<p>同样进入安装页面，先停止所有容器。</p>
<pre><code class="language-bash">cd /root/data/docker_data/babelduck

docker compose down

cd ..

rm -rf /root/data/docker_data/babelduck  # 完全删除
</code></pre>
<p>可以卸载得很干净。</p>
<h2 id="9--常见问题及注意点">9. 常见问题及注意点</h2>
<p>logo的图片无法显示，暂时不知道啥情况</p>
<h2 id="10--结尾">10. 结尾</h2>
<p>祝大家用得开心，有问题可以去 GitHub 提 <a href="https://github.com/Orenoid/BabelDuck/issues">Issues</a>，也可以在评论区互相交流探讨。</p>
<p>同时，有能力给项目做贡献的同学，也欢迎积极加入到 <a href="https://github.com/Orenoid/BabelDuck">项目</a> 中来，贡献自己的一份力量！</p>
<p>最后，感谢开发人员们的辛苦付出，让我们能用到这么优秀的项目！</p>
<h2 id="参考资料">参考资料</h2>
<p>官方GitHub：<a href="https://github.com/Orenoid/BabelDuck">https://github.com/Orenoid/BabelDuck</a></p>]]></description><guid isPermaLink="false">/archives/docker-compose-install-babelduck</guid><dc:creator>咕咕</dc:creator><category>Docker系列</category><pubDate>Tue, 17 Dec 2024 06:35:13 GMT</pubDate></item></channel></rss>