尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Docker部署Alist配置SSL证书:从选型到自动续期全攻略

Docker部署Alist配置SSL证书:从选型到自动续期全攻略 1. 为什么Docker里的Alist一定要配SSL证书先说个我自己的经历。很早之前我在一台小机器上用Docker跑Alist图省事直接用http://IP:5244访问用了大半年一直没当回事。后来有一次在外部网络环境下列表文件浏览器直接弹了个“不安全连接”的警告我当时还以为是浏览器抽风随手点了继续。直到有一天我发现自己登录Alist管理后台的时候被某个中间环节截了密码——虽然那次没有造成实际损失但让我彻底明白了一个道理任何暴露在公网的服务没有SSL证书就等于裸奔。Alist这个项目本身是一个支持多存储协议的文件列表程序很多人拿它当网盘聚合入口挂载各种云盘、本地目录、对象存储。它会涉及账号密码、Token、文件元数据等敏感信息。如果只在局域网里玩那HTTP尚可接受但只要你做了端口映射、用域名访问、或者让朋友从外面访问你的Alist就必须用HTTPS。SSL证书的核心作用不复杂一是加密传输内容防止中间人窃听二是验证服务器身份让用户确信访问的是你的服务而不是冒牌货。Docker部署Alist的场景有点特殊容器本身只监听HTTP端口证书配置不在Alist应用内部完成而是通过外层反代、Docker端口映射、或挂载证书文件等方式实现。这就导致很多人在这个环节卡壳——明明证书申请好了却不知道应该放在哪里、怎么让Alist用上。这篇文章就专门说清楚这件事手把手带你把Docker里的Alist加上SSL证书顺便把自动续期和排查问题的方法也一并讲了。如果你是刚接触Docker或者刚接触Alist这篇文章同样适合你。我会尽量把原理讲清楚把每一步的命令和配置文件都贴全你照着复制粘贴基本就能跑通。如果你已经是老手重点看第3章的架构选型和第5章的避坑排查那部分是我实操中积累的硬经验。2. 三种主流证书获取方式到底该怎么选给Alist配SSL证书第一步不是操作而是选型。证书从哪来、怎么续期直接决定了你后续的维护成本和使用体验。目前主流的选择有三种云厂商免费证书、Lets Encrypt免费证书、以及自签名证书。各有各的适用场景我分别说下。2.1 阿里云免费证书国内访问友好手动续期阿里云SSL证书服务每年都可以申请免费的单域名证书一般有效期是3个月具体以控制台展示为准。这种证书的优点是国内链路访问体验好兼容性高品牌信任度高缺点是续期需要登录控制台手动操作每年好几次容易忘记。热词里提到的“阿里云ssl证书免费续期”我理解说的就是这件事。实际操作流程是登录阿里云控制台进入数字证书管理服务。在SSL证书页面点击“申请免费证书”填写域名。按提示完成域名验证一般有DNS验证和文件验证两种模式。DNS验证需要你到域名解析处加一条TXT记录。签发成功后下载证书文件会得到一个PEM格式的证书文件和KEY私钥文件。把这两个文件放到服务器上配置到Nginx/Caddy等反代服务中。注意阿里云免费证书一个自然年内有数量限制之前是20个现在是每年50个左右具体看活动个人使用完全够。但如果你手头有十来个域名要配建议还是考虑Lets Encrypt全自动方案。我对这种方式的评价是国内站点、用阿里云DNS解析、一年手动续几次也不嫌烦的人选它最省心。特别是你的域名本身就在阿里云买的DNS验证操作非常快。2.2 Lets Encrypt免费证书全自动续期运维友好Lets Encrypt是目前全球使用量最大的免费证书颁发机构证书有效期90天但支持通过acme.sh或certbot定时任务自动续期。配上泛域名证书申请能力一个证书可以覆盖所有子域名。我自己的Alist就是用这种方式。优点非常明显免费没有任何数量限制。自动化程度高配置好之后基本不用管。支持通配符证书*.example.com一个证书搞定所有子服务。与Caddy、Nginx等反代工具集成得很好。缺点是Lets Encrypt的证书链在国内某些网络条件下偶尔出现验证慢的现象但实际使用中影响不大另外续期依赖服务器上的定时任务如果机器长期关机或任务被干掉证书就可能过期。对于需要长期稳定运行、追求“一劳永逸”的Docker用户我优先推荐Lets Encrypt配合acme.sh的方案。第4章我会给出完整配置。2.3 自签名证书仅限内网测试自签名证书就是自己当CA签发的证书浏览器会报“不受信任”。它只适合纯内网测试、临时调试、或者用在开发环境。如果你只是在家里用Docker跑Alist不打算映射到公网那自签名也能凑合但只要你打开浏览器看到红色警告就烦躁就别费这个劲了。Windows上“windows生成ssl证书”这类热词通常指的就是用OpenSSL自签证书或者用PowerShell的New-SelfSignedCertificate命令。我不建议在生产环境用自签证书因为浏览器信任问题会带来大量误报和用户困惑。我的结论很简单公网服务用Lets Encrypt或云厂商证书内网测试用自签不要在这件事上纠结太久。3. Docker部署Alist的SSL配置架构选型Alist官方Docker镜像默认监听5244端口直接暴露HTTP服务。给这个服务加SSL本质上就是两种做法要么在Alist前面加一层能终结HTTPS的反代服务要么直接让Docker端口映射时承担加密工作——但后者并不现实因为端口映射本身不处理加密。所以实际可行的架构有三种。3.1 方案ANginx反代 证书文件这是最传统、最通用的方式。你在宿主机或另一个容器里跑Nginx把443端口映射到宿主机然后Nginx把请求转发给Alist容器的5244端口。证书文件配置在Nginx里。你可能会问为什么非要加一层Nginx不能直接让Alist支持HTTPS吗Alist的新版本其实有证书配置选项但直接在容器里挂证书有个问题证书续期时要重启容器而且日志、报错、性能调优都绑在Alist进程上不如让专业的HTTP服务器干专业的活。Nginx处理SSL、静态文件、连接复用都是一把好手Alist专注做文件列表服务各司其职更合理。nginx配置示例大概长这样server { listen 443 ssl http2; server_name alist.example.com; ssl_certificate /etc/nginx/certs/alist.example.com/fullchain.pem; ssl_certificate_key /etc/nginx/certs/alist.example.com/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://127.0.0.1:5244; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }用不用独立容器跑Nginx两种选择都有道理。宿主机安装Nginx生态成熟但污染了宿主机环境用docker-compose把Alist和Nginx编排在一起则更整洁。我建议用docker-compose统一管理这样迁移、备份、重建都方便也很符合“Docker部署Alist”的场景设定。3.2 方案BCaddy反代 自动证书Caddy是我特别想推荐给新手的方案因为它内置了自动HTTPS功能。你只需要写一行配置Caddy会自动申请证书、配置续期、处理HTTP到HTTPS跳转。如果你用的是Lets Encrypt方案Caddy可以让复杂度再降一个维度。Caddyfile配置如下alist.example.com { reverse_proxy alist:5244 }就这么多。Caddy会自动为alist.example.com申请和续期Lets Encrypt证书。你不需要手动放证书文件不需要写复杂的SSL配置段不需要操心续期任务。对于只想快速把Alist跑起来、不想折腾Nginx配置的人来说Caddy是体验最好的方案。但它也有缺点Caddy默认申请证书走的是Lets Encrypt在大陆网络环境下偶发挑战失败而且Caddy的配置语法虽然简单但出了问题排错时社区资料没有Nginx那么丰富。如果你的环境网络访问国外正常Caddy绝对是个好选择。3.3 方案CNginx Proxy Manager可视化配置如果你不喜欢写配置文件喜欢图形化管理那么Nginx Proxy ManagerNPM值得一试。它本质上是Nginx的封装提供Web界面让你在浏览器里完成域名绑定、证书申请、反向代理配置。从热词里看很多人对这类“面板化”工具接受度很高。在NPM里给Alist加SSL流程是新建一个Proxy Host域名填alist.example.com转发IP填Alist容器名或IP端口填5244。SSL选项卡里选择“Request a new SSL Certificate”填邮箱和域名。保存后NPM自动申请证书并配置HTTPS。NPM对新手友好界面逻辑清晰而且证书管理面板里能看到到期时间、手动续期按钮。缺点是NPM本身也是一个Docker容器你需要额外分配80和443端口给它在你机器上如果已经有Nginx占用了这些端口就得先处理冲突。提示无论你选择Nginx、Caddy还是NPM核心要点都一样——让一个持久运行的进程持有443端口并维护证书文件。Alist容器本身不需要知道证书的存在它只负责提供HTTP服务。4. 完整实操使用acme.sh Nginx给Docker里的Alist加SSL这一章我以Ubuntu 22.04 Docker Compose Nginx反代为例完整走一遍从申请证书到配置完成的流程。这个方案适合多数人也是我实际生产环境的配置。整个过程分四步。4.1 第一步用docker-compose编排Alist和Nginx先看一下目录结构。我习惯把Alist和Nginx放同一个compose文件里这样一条命令就能启动整套服务。mkdir -p /opt/alist-ssl/{data,nginx/certs,nginx/conf} cd /opt/alist-ssl编写docker-compose.ymlversion: 3.8 services: alist: image: xhofe/alist:latest container_name: alist restart: always volumes: - ./data:/opt/alist/data environment: - PUID0 - PGID0 - UMASK022 # 不直接映射端口由Nginx内部转发避免端口暴露风险 networks: - alist-net nginx: image: nginx:stable-alpine container_name: alist-nginx restart: always ports: - 80:80 - 443:443 volumes: - ./nginx/conf:/etc/nginx/conf.d - ./nginx/certs:/etc/nginx/certs networks: - alist-net networks: alist-net: driver: bridge注意几个细节Alist容器不映射端口到宿主机只有Nginx暴露80和443这样外部无法直接通过5244端口绕过HTTPS访问Alist。./data目录持久化Alist配置和数据库删除容器不丢数据。Nginx的证书目录挂在宿主机上后续acme.sh写证书文件就能直接生效。先启动AlistNginx还没配置先不急着启动也可以直接整体启动也行反正Nginx配置缺失不影响Alist启动docker-compose up -d alist docker exec -it alist ./alist admin random第二条命令会输出Alist管理员的初始账号密码。记下来后面登录后台用。4.2 第二步安装acme.sh并申请证书acme.sh是一个用Shell脚本实现的ACME客户端非常轻量配合cron实现自动续期。安装方式一行命令curl https://get.acme.sh | sh -s emailyouremailexample.com安装完成后需要重新加载shell环境变量然后配置DNS API实现自动验证。我以阿里云为例因为热词里提到阿里云相关而且国内用阿里云DNS解析域名的人多export Ali_Key你的阿里云AccessKey ID export Ali_Secret你的阿里云AccessKey Secret acme.sh --issue --dns dns_ali -d alist.example.com提示AccessKey需要具有DNS管理的权限建议在RAM里创建子用户只授权AliyunDNSFullAccess不要用主账号Key安全习惯要养成。签发成功后把证书安装到Nginx的证书目录acme.sh --install-cert -d alist.example.com \ --key-file /opt/alist-ssl/nginx/certs/alist.example.com/key.pem \ --fullchain-file /opt/alist-ssl/nginx/certs/alist.example.com/fullchain.pem \ --reloadcmd docker exec alist-nginx nginx -s reload--fullchain-file会写入包含证书链的完整文件Nginx需要的就是这个。最后的reloadcmd参数定义了证书更新后自动执行的操作——这里通过docker exec让Nginx容器重载配置。如果你用宿主机Nginx就改成nginx -s reload。4.3 第三步编写Nginx配置并启动在/opt/alist-ssl/nginx/conf/目录下新建alist.confserver { listen 80; server_name alist.example.com; # 强制跳转HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name alist.example.com; ssl_certificate /etc/nginx/certs/alist.example.com/fullchain.pem; ssl_certificate_key /etc/nginx/certs/alist.example.com/key.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; client_max_body_size 500M; location / { proxy_pass http://alist:5244; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; } }关于这段配置的几点解释proxy_pass http://alist:5244;用的是docker-compose服务名alist在同一个networks里可以直接通过服务名访问不需要关心Alist容器的实际IP这是Compose网络的一个便利特性。client_max_body_size 500M;允许上传大文件。Alist本身支持文件上传大小限制要在这里放开否则上传超过默认1MB的文件会被Nginx直接拒掉。proxy_set_header X-Forwarded-Proto $scheme;把协议头传交给Alist这样Alist后台能看到真实访问协议某些情况下影响重定向链接的生成。保存配置后启动整个服务栈docker-compose up -d然后检查Nginx是否正常运行docker ps docker logs alist-nginx -f如果一切正常Nginx日志里不会有报错。这时用浏览器访问https://alist.example.com你应该能看到安全的HTTPS锁标志了。4.4 第四步验证证书自动续期acme.sh默认安装了cron任务你可以手动检查续期任务是否存在crontab -l正常情况下会有一条记录0 0 * * * /root/.acme.sh/acme.sh --cron --home /root/.acme.sh /dev/null想手动模拟一次续期可以运行acme.sh --cron --force这个命令会检查证书有效期如果剩余时间大于60天则不会重复签发加--force才会强制更新。验证逻辑没问题之后你的证书就处于自动续期状态了。5. SSL配置中最常见的5个坑与排查方案我见过很多人本来配好了SSL结果一个低级错误导致网站打不开或者重启后证书突然失效。这里把我踩过的坑和排查经验完整列出来。5.1 证书文件权限或路径错误Nginx启动时报[emerg] cannot load certificate几乎都是证书路径写错或者权限不对。排查方法docker exec -it alist-nginx ls -l /etc/nginx/certs/alist.example.com/确认fullchain.pem和key.pem都在。如果只有root用户可以读Nginx工作进程可能无法访问。我一般统一执行chmod 644 /opt/alist-ssl/nginx/certs/alist.example.com/*注意私钥文件理论上权限可以收紧到600但由于Nginx容器内的用户映射机制644更稳妥。如果你追求严格安全可以单独设置容器的user映射但那属于进阶操作。5.2 容器重启后证书目录丢失这是docker-compose挂载路径写错导致的。如果你把证书放在了容器可写层而不是宿主机挂载目录容器重建时数据就会丢失。解决办法是确认docker-compose.yml里的volumes挂载点与实际路径一致。我在第4章示例中把证书路径统一放在./nginx/certs目录下容器删除重建后证书依然存在。5.3 强制HTTPS跳转导致死循环如果你同时配置了http - https跳转但Nginx的proxy_pass又把请求转发到Alist时带有X-Forwarded-Proto头不正确可能触发死循环。一个典型的错误配置是Alist后台设置了“站点地址”为https://alist.example.com但X-Forwarded-Proto头没有传过去导致Alist生成的重定向链接还是HTTP。你需要注意在Nginx里把X-Forwarded-Proto带上同时到Alist后台管理的“设置-基础设置-站点地址”中填写完整的HTTPS地址。这样两边保持一致就不会有跳转循环问题。5.4 防火墙或安全组没有放开443端口如果你的browser显示连接超时但证书检查一切正常很可能就是443端口压根没通。检查云安全组和本机防火墙ufw status verbose iptables -L -n ss -tlnp | grep 443如果用的是云服务器登录控制台查看安全组是否放行了TCP 443入方向规则。很多云厂商默认只开22和80443要手动加规则。5.5 acme.sh续期后Nginx没有重载acme.sh自动续期成功后需要触发Web服务重载才能让新证书生效。我在第4章的--reloadcmd里写了docker exec alist-nginx nginx -s reload这是关键。但很多教程里没有这一步导致证书明明已经续期Nginx还在用旧证书文件。验证你是否遇到这个问题可以看Nginx日志docker logs alist-nginx --tail 50如果看到类似NGINX reloaded的日志说明reload执行了。检查证书实际生效时间openssl x509 -enddate -noout -in /opt/alist-ssl/nginx/certs/alist.example.com/fullchain.pem输出里的notAfter时间应该是新的到期日这就说明证书和Nginx都正常。6. 从Nginx换到Caddy后的体验对比第4章我给的方案以Nginx为主但我在另一台机器上用Caddy也跑了一套Alist。这里给你做个坦诚的对比。如果你不想维护Nginx配置文件我建议直接上Caddy。Caddy的compose配置长这样version: 3.8 services: alist: image: xhofe/alist:latest container_name: alist restart: always volumes: - ./data:/opt/alist/data networks: - alist-net caddy: image: caddy:2-alpine container_name: alist-caddy restart: always ports: - 80:80 - 443:443 volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data networks: - alist-net volumes: caddy_data: networks: alist-net: driver: bridge对应的Caddyfilealist.example.com { reverse_proxy alist:5244 encode gzip }Caddy会自动在/data卷里维护证书文件自动续期无需你介入。如果你用Cloudflare DNS甚至可以在Caddyfile中添加tls指令选择DNS挑战方式对那种不开放80端口的网络环境很友好。从两者对比来看我给个表格供你快速判断对比项Nginx方案Caddy方案配置难度中等需要理解server块极低三行配置搞定证书管理需要额外接acme.sh内置集成完全自动化扩展性强支持各种高级路由和限流较弱但日常反代够用资源占用更低略高但可忽略调试便利日志清晰资料多日志简洁资料相对少适用人群有Nginx经验或追求高性能新手优先我用Nginx的原因很简单环境里已经跑了很多其他服务Nginx统一管理更顺手。如果你是从零开始、只服务Alist一个WEB应用直接选Caddy没必要折腾Nginx。7. 实操心得我的Alist SSL部署习惯最后聊几个我的个人操作习惯供你参考。这些是我使用了很长时间后沉淀下来的经验不是教条但确实能省很多麻烦。第一域名永远比IP可靠。即使你暂时没有域名也可以用一个免费二级域名或者花生壳之类的动态域名先配上SSL。用IP访问时证书是不好签发的Lets Encrypt从2025年开始已经陆续支持IP证书了但云厂商免费证书还不支持流程会麻烦很多。一个域名一年就几十块钱没必要省。第二不要把证书文件放在容器可写层内。这是血泪教训——有一天我想升级Alist镜像顺手docker-compose up -d重建了容器结果证书没了网站瞬间变回HTTP。从那以后我把Alist和反代服务的所有持久化数据都放在宿主机目录或者独立volume里容器重建一百次也不怕。第三开启HTTP/2。Nginx配置里的listen 443 ssl http2能显著提升HTTPS下的访问速度尤其是Alist展示大量文件列表时并发请求多HTTP/2的多路复用优势明显。第四记得在Alist后台开启“站点地址”配置。在Alist管理后台的设置-基础设置里把“站点地址”填成https://alist.example.com。这一步很多人会漏掉导致后台生成的分享链接、下载链接都是HTTP开头的用户点进去又走一遍不安全连接。第五定期看看证书状态。自动化再稳定也要防患于未然。我习惯每个月做一次巡检acme.sh --list顺便看一眼证书到期输出心里有数。如果你部署的机器不多一个浏览器收藏夹把证书状态链接放进去也行。别等到用户跟你反馈“网站证书过期了”才来处理那种局面对谁都不好看。踩过几次坑之后我现在每台运行Alist的机器都固定使用同一套部署模板Docker Compose编排、反代终止SSL、acme.sh自动续期、域名访问、强制HTTPS。这套配置我迁移过好几台机器从2核4G的小鸡到8核16G的独服都稳定运行。你按照这篇文章的步骤走一遍大概率也能一次跑通。中间如果遇到别的问题欢迎带着具体报错信息来交流我可以把这篇内容继续往更细的方向扩展。
返回列表