969 字
5 分钟

DokPloy 部署Garage与登录失败排查

背景#

MinIO 进入维护模式#

2025年12月3日,MinIO 官方宣布开源项目进入维护模式:

  • 停止接受新功能和 PR
  • 不再积极处理现有 Issue 和 PR
  • 仅对严重安全漏洞”视情况而定”修复
  • 社区支持仅限”尽力而为”

这一举措在开源社区引发强烈反响。

image-20260108175153529

为什么选择 Garage#

deuxfleurs-org
/
garage
Waiting for api.github.com...
00K
0K
0K
Waiting...

Garage 是一个用 Rust 编写的分布式对象存储系统,具有以下特点:

  • S3 兼容:可作为 MinIO 的平替
  • 轻量级:单二进制文件,资源占用低
  • 去中心化:适合边缘部署和多节点场景
  • 自托管友好:配置简单,易于维护

配合 Garage WebUI 可以获得可视化管理界面:

khairul169
/
garage-webui
Waiting for api.github.com...
00K
0K
0K
Waiting...

Dokploy 部署配置#

在 Dokploy 中部署 Garage + WebUI,需要配置以下环境变量:

直接选择模板部署

image-20260108174433376

# WebUI 环境变量
API_BASE_URL=http://garage:3903 # Admin API(内部通信,使用服务名)
S3_ENDPOINT_URL=http://garage:3900 # S3 API(内部通信)
# 认证配置(使用 htpasswd 生成)
AUTH_USER_PASS=admin:$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

密码生成

Terminal window
htpasswd -nbBC 10 "YOUR_USERNAME" "YOUR_PASSWORD"

如果没有的htpasswd库的,需要安装 apache2-utils

Garage 端口说明

端口用途外部访问域名示例
3900S3 APIgarage.xx.com
3901RPC (节点通信)仅内部
3902Web 静态托管可选配置
3903Admin API仅内部
3909WebUIgarage-ui.xx.com
TIP

API_BASE_URLS3_ENDPOINT_URL 使用 Docker 服务名 garage 而非外部域名,因为这是容器间内部通信。

问题一:登录失败#

现象#

使用 htpasswd 生成了正确格式的密码哈希:

Terminal window
htpasswd -nbBC 10 "admin" "your-password"
# 输出: admin:$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

配置到 .env 文件中:

Terminal window
AUTH_USER_PASS=admin:$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

但登录时始终提示账户密码错误。

排查过程#

使用 docker inspect 查看容器内实际收到的环境变量:

Terminal window
docker inspect garage-webui-1 --format '{{range .Config.Env}}{{println .}}{{end}}'

发现问题:

AUTH_USER_PASS=admin:$2y$10

密码哈希被截断了!期望的完整值是 admin:$2y$10$xxxxxx...,但实际只有 admin:$2y$10

原因分析#

WARNING

Docker Compose 会将 .env 文件中的 $ 解释为变量替换符号。

bcrypt 哈希中包含多个 $ 符号(如 $2y$10$Qtra4...):

  • $2y 被当作变量 2y
  • $10 被当作变量 10
  • $Qtra4... 被当作变量 Qtra4...

由于这些变量不存在,Docker Compose 将它们替换为空字符串,导致哈希被截断。

解决方案#

docker-compose.yml 中直接硬编码环境变量,使用 $$ 转义 $ 符号:

services:
garage-webui:
environment:
- AUTH_USER_PASS=admin:$$2y$$10$$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- API_BASE_URL=http://garage:3903
- S3_ENDPOINT_URL=http://garage:3900
TIP

$$ 在 Docker Compose 中会被转义为单个 $,这样密码哈希就能完整传递给容器了。

问题二:升级后状态显示 Unavailable#

现象#

将 Garage 从 v2.0.0 升级到 v2.1.0 后,WebUI 显示连接状态为 Unavailable

排查过程#

查看 Garage 日志:

Terminal window
docker logs garage-1 --tail 30

发现大量错误:

WARN Response: error 500 Internal Server Error, Internal error: Layout not ready

检查集群状态:

Terminal window
docker exec garage-1 /garage status

输出显示节点没有分配角色:

==== HEALTHY NODES ====
ID Hostname Address Tags Zone Capacity Version
7740e73cc75036ef 67993cf5 [::1]:3901 NO ROLE ASSIGNED v2.1.0

原因分析#

IMPORTANT

升级 Garage 后,需要重新配置集群布局(Cluster Layout)。节点没有分配角色时,无法提供 S3 服务。

解决方案#

  1. 分配节点角色
Terminal window
docker exec garage-1 /garage layout assign -z dc1 -c 1G 7740e73cc75036ef

参数说明:

  • -z dc1:Zone 名称
  • -c 1G:分配的存储容量
  • 7740e73cc75036ef:节点 ID(从 status 命令获取)
  1. 应用布局更改
Terminal window
docker exec garage-1 /garage layout apply --version 1
  1. 验证状态
Terminal window
docker exec garage-1 /garage status

现在应该显示:

==== HEALTHY NODES ====
ID Hostname Address Tags Zone Capacity DataAvail Version
7740e73cc75036ef 67993cf5 [::1]:3901 [] dc1 1000.0 MB 978.9 GB v2.1.0

刷新 WebUI,连接状态应恢复正常。

总结#

问题原因解决方案
登录失败Docker Compose $ 变量替换使用 $$ 转义
登录不稳定多个容器负载均衡删除旧容器
Unavailable升级后节点无角色layout assign + apply
NOTE

在 Dokploy 中管理 Docker Compose 项目时,环境变量的特殊字符处理需要特别注意。直接在 docker-compose.yml 中硬编码可以避免 .env 文件的变量替换问题。

界面预览#

界面还是挺不错,简洁又好看。

image-20260108174812353

image-20260108174831129

DokPloy 部署Garage与登录失败排查
https://catcat.blog/2026/01/dokploy-garage-s3-deployment-guide
作者
猫猫博客
发布于
2026-01-08
许可协议
CC BY-NC-SA 4.0