Skip to content

Docker 安装 SeaweedFS

官方镜像:https://hub.docker.com/r/chrislusf/seaweedfs

Github: https://github.com/seaweedfs/seaweedfs

官方文档:https://github.com/seaweedfs/seaweedfs/wiki

端口说明

端口说明:https://github.com/seaweedfs/seaweedfs/blob/master/docker/Dockerfile.local

端口描述
9333master server shared http port
8080volume server http port
8888filer server http port
8333s3 server http port
23646Admin UI
7333webdav server http port
19333master server shared grpc port
18080volume server grpc port
18888filer server grpc port

关于应该开放哪些端口的问题:

  • 如果只使用 master 服务上传文件:需开放 master server 9333 上传端口,需开放 volume server 8080下载端口,并且 volume server 启动时,要使用 -publicUrl 参数指定外部访问地址。
  • 如果只使用 filer 服务上传/下载文件:需开放 filer server 8888 端口。
  • 如果只使用 s3 服务上传/下载文件:需开放 s3 server 8333 端口。
  • 如果使用 Admin UI 服务(Web 控制台):需开放 Admin UI 23646 端口。

单机快速启动(推荐)

一条命令启动所有组件(master, volume, filer, s3),简单快捷。适用于开发测试、快速体验。

shell
# 查看更多配置参数 `weed server --help` 帮助命令
docker run --rm seaweedfs:3.99 server --help
shell
docker run \
--name seaweedfs \
--restart=unless-stopped \
--network network_default \
-p 9333:9333 \
-p 8080:8080 \
-p 8888:8888 \
-p 8333:8333 \
-v /opt/seaweedfs/data:/data \
-d chrislusf/seaweedfs:3.99 server -filer -s3 -dir="/data" -volume.publicUrl="<公网ip或域名>:<端口>"
  • 其它 weed server --help 命令的参数可根据需要添加。

    • -filer-s3 也可以根据需要只使用其中的一个。
      • -filer:启用 filer server。
      • -s3:启用 s3 server。
    • -dir="/data": 默认数据路径是 /tmp
    • -volume.publicUrl="seaweedfs.volume.aday.fun:8080": 指定 volume 的公网外部访问地址。
  • master 服务浏览器访问:http://localhost:9333

  • volume 服务浏览器访问:http://localhost:8080/ui/index.html,也可从 master ui 页面点击进入。

  • filer 服务浏览器访问(未验证):http://localhost:8888

  • s3 服务浏览器访问(未验证):http://localhost:8333

Admin UI 需单独部署

shell
# 查看 `weed admin --help` 所有参数
docker run --rm seaweedfs:3.99 admin --help
shell
docker run \
--name seaweedfs-admin \
--restart=unless-stopped \
--network network_default \
-p 23646:23646 \
-d chrislusf/seaweedfs:3.99 admin -adminUser="admin" -adminPassword="123456" -masters="seaweedfs:9333"
  • -adminUser="admin":指定 Web 登录页面的用户名。
  • -adminPassword="123456":指定 Web 登录页面的密码。不增加该参数则默认无需登录,这在公网环境下不安全。
  • -masters="seaweedfs:9333": 配置容器名称(seaweedfs)的前提是:需要通过 --network network_default 参数把 seaweedfs 和 seaweedfs-admin 放在同一个网络中。

分离模式启动

分别启动各个组件,配置更灵活。适用于生产环境、集群部署。

  • 单机模式不推荐,得多启动一些服务。
  • 集群模式下推荐。

master 服务

shell
# 查看帮助
docker run --rm seaweedfs:3.99 master --help
shell
docker run \
--name seaweedfs-master \
--restart=unless-stopped \
--network network_default \
-p 9333:9333 \
-d chrislusf/seaweedfs:3.99 master

volume 服务

shell
# 查看帮助
docker run --rm seaweedfs:3.99 volume --help
shell
docker run \
--name seaweedfs-volume \
--restart=unless-stopped \
--network network_default \
-p 8080:8080 \
-d chrislusf/seaweedfs:3.99 volume -mserver=<master_host>:9333 -port=8080 -publicUrl="你的公网IP或域名:8080"

filer 服务

shell
# 查看帮助
docker run --rm seaweedfs:3.99 filer --help
shell
docker run \
--name seaweedfs-filer \
--restart=unless-stopped \
--network network_default \
-p 8888:8888 \
-d chrislusf/seaweedfs:3.99 filer -mserver=<master_host>:9333

s3 服务

shell
# 查看帮助
docker run --rm seaweedfs:3.99 s3 --help
shell
docker run \
--name seaweedfs-s3 \
--restart=unless-stopped \
--network network_default \
-p 8333:8333 \
-d chrislusf/seaweedfs:3.99 s3 -mserver=<master_host>:9333

Admin UI 服务

和上面相同,此处省略。

master 文件上传

如果使用 master 服务端口来进行文件上传,需要开放 master server 9333 端口用作上传,需要开放 volume server 8080 端口用作文件下载。

启动的时候也只需要 master 和 volume 两个服务。

API 分两步上传

调用 masert HTTP API 来上传文件,首先,需要向 Master 节点的 /dir/assign 接口请求,获取一个可供上传的文件卷位置和一个唯一的 FID。

从 Master 获取文件卷和 FID

shell
# 后缀固定值:/dir/assign
curl http://localhost:9333/dir/assign

# 返回值
{"fid":"1,017aebc93e","url":"172.18.0.2:8080","publicUrl":"172.18.0.2:8080","count":1}

返回的 JSON 结果中,fid 字段(例如 1,017aebc93e)和 url 字段(例如 172.18.0.2:8080)是下一步所需的关键信息。

向 Volume 服务器上传文件

拿到 FID 和 Volume 服务器的 URL 后,就可以使用 HTTP POST 请求将文件内容发送到指定的 Volume 服务器。

shell
curl -F file=@/path/to/your/file.txt http://172.18.0.2:8080/1,017aebc93e

# 示例
# 创建一个 demo.txt 文件到当前目录
echo "这是一个测试文件!" > demo.txt

# 上传当前目录下的 demo.txt 文件到服务器
curl -F file=@$PWD/demo.txt http://localhost:8888/test/

但是此处的 volume ip 是 docker 内网的 ip, 外部是无法访问的,咱没研究该如何解决。

API 一步直接上传(推荐)

一步直接上传,可通过 master 服务的 /submit 接口直接上传,免去了通过 /dir/assign 接口申请 fid 的步骤。

shell
# 后缀固定值:/submit
curl -F file=@/path/to/your/file.txt http://localhost:9333/submit


# 示例
# 创建一个 demo.txt 文件到当前目录
echo "这是一个测试文件!" > demo.txt

# 上传当前目录下的 demo.txt 文件到服务器
curl -F file=@$PWD/demo.txt http://localhost:9333/submit

# 返回
{"eTag":"e13f6ed2","fid":"1,017aebc93e","fileName":"demo.txt","fileUrl":"172.18.0.2:8080/1,017aebc93e","size":17}

master 文件下载(实际是通过 volume)

如果已知文件存储的 volume server 的话,可通过:http://<volume_server_ip>:8080/<fid> 来下载文件。其中 8080 为 volume server 的端口号。

另外,一般上传后,会返回一个 fileUrl,比如:172.18.0.2:8080/1,017aebc93e,可通过这个地址下载(实际上还是 volume server 的下载地址和端口)。

shell
# 示例
curl -X GET -o download.txt "http://localhost:8080/1,017aebc93e"

master 文件删除

master 文件下载 章节类似,只是 http 请求方式需要为 DELETE

shell
curl -X DELETE http://localhost:8080/1,017aebc93e

filer 文件上传

txt
请求格式:向 http://<filer地址>:<端口>/<路径> 发起一个 multipart/form-data 类型的 POST 请求。
其中,文件数据放在名为 file 的表单字段中。

示例(使用 curl):

假设你的 Filer 运行在 localhost:8888,想将本地文件 demo.txt 上传到 Filer 的 /test 目录下。

shell
curl -F file=@/path/to/your/local/demo.txt http://localhost:8888/test/

# 创建一个 demo.txt 文件到当前目录
echo "这是一个测试文件!" > demo.txt

# 上传当前目录下的 demo.txt 文件到服务器
curl -F file=@$PWD/demo.txt http://localhost:8888/test/

如果上传成功,Filer 会返回一个包含文件详细信息的 JSON 响应。

json
{
  "name":"demo.txt",
  "size":364581
}

filer 文件下载

通过 Admin UI 可以查看文件,需要先安装 Admin UI 服务。

curl 下载

txt
访问格式:http://<filer地址>:<端口>/<文件路径>
shell
# 示例:使用 curl 调用 Filer 接口
# 直接查看文件的内容
curl http://localhost:8888/test/demo.txt

# 下载文件并重命名到当前所在目录
curl -o download.txt http://localhost:8888/test/demo.txt

浏览器下载

shell
# 浏览器访问 8888 filer server 即可下载。
http://localhost:8888/test/demo.txt

# filer 总目录
http://localhost:8888

全局启动 JWT 认证

默认 volume server 没有认证,,这在内网环境下问题不大,但如果要暴露到公网,就需要添加 JWT 保护。

生成默认的配置文件 security.toml

shell
# 在宿主机上执行此命令,生成默认的 security.toml 文件到路径 /opt/seaweedfs/security.toml 下
docker run --rm chrislusf/seaweedfs:3.99 scaffold -config=security > /opt/seaweedfs/security.toml

生成密钥 key

需要为 jwt.filer_signing.keyjwt.filer_signing.read.key 分别生成两个不同的密钥 key。

后续需要根据这个 key 来使用 JWT 工具栏生成一个 JWT token,以供文件的上传和下载使用。

shell
# 执行两次,生成两个密钥
openssl rand -base64 32

# 生成结果类似这样的两个字符串
AfpqdFEUpOzBQkwFWBW8lWiC9D33wRXycKBKOAh6wvM=

修改密钥

把上面生成的密码配置到如下位置:

toml
# 如果此JWT密钥已配置,则Filer仅接受使用此JWT签名的HTTP写入请求[citation:1]
[jwt.filer_signing]
key = "你的写入密钥"                  # 在此处填入你的密钥字符串
expires_after_seconds = 10           # seconds

# 如果此JWT密钥已配置,则Filer仅接受使用此JWT签名的HTTP读取请求[citation:1]
[jwt.filer_signing.read]
key = "你的读取密钥"                  # 在此处填入你的密钥字符串
expires_after_seconds = 10           # seconds

挂载配置文件启动

注意:把 security.toml 挂载到 /etc/seaweedfs/security.toml 位置,即可自动读取。

txt
# Put this file to one of the location, with descending priority
#    ./security.toml
#    $HOME/.seaweedfs/security.toml
#    /etc/seaweedfs/security.toml
# this file is read by master, volume server, filer, and worker
shell
docker run \
--name seaweedfs \
--restart=unless-stopped \
-p 8888:8888 \
-v /opt/seaweedfs/security.toml:/etc/seaweedfs/security.toml \
-v /opt/seaweedfs/data:/data \
-d chrislusf/seaweedfs:3.99 server -filer -s3 -dir="/data"

注:这里只映射了 8888 filer 端口,即只选择了使用 filer 服务来上传/下载文件。

使用 JWT 来上传或下载文件的三种使用方式

  • Bearer Token: 通过设置请求头:Authorization: Bearer <token>
  • jwt=token 后缀:通过请求的查询参数:http://localhost:8888/buckets/all?jwt=token
  • 在一个名为AT(访问令牌)的 HTTP-only cookie 中

生成 JWT token

java
@Test
public void generateJwt() {
  // 这里的 key 就是使用 openssl 生成的密钥 key 
  String key = "AfpqdFEUpOzBQkwFWBW8lWiC9D33wRXycKBKOAh6wvM=";
  String token = JWTUtil.createToken(null, key.getBytes(StandardCharsets.UTF_8));
  log.info(token);

  boolean verify = JWTUtil.verify(token, key.getBytes(StandardCharsets.UTF_8));
  Assertions.assertTrue(verify);
}

生成的 JWT 格式:eyJ0eXAiO4JKV1QiLCJhbGciO3JIUzI1NiJ9.e30.xtrTYsadhSeqg6bjBR4gMUkIETvADSI1EJQItCP8Uds

filer 启用 JWT 后的文件上传

格式:这里要用写操作的 JWT 令牌。即通过 jwt.filer_signing.key 生成的 token

shell
curl -X POST \
  -H "Authorization: Bearer 你的写操作JWT令牌" \
  -F "file=@/path/to/your/local/file.jpg" \
  http://127.0.0.1:8888/path/to/upload/
shell
# 格式(这里要用写操作的 JWT 令牌。即通过 `jwt.filer_signing.key` 生成的 token)
curl -X POST \
  -H "Authorization: Bearer 你的写操作JWT令牌" \
  -F "file=@/path/to/your/local/file.jpg" \
  http://127.0.0.1:8888/path/to/upload/

# 示例 (使用 Authorization 请求头)
curl -X POST \
  -H "Authorization: Bearer eyJ0eXAiO4JKV1QiLCJhbGciO3JIUzI1NiJ9.e30.xtrTYsadhSeqg6bjBR4gMUkIETvADSI1EJQItCP8Uds" \
  -F "file=@/path/to/your/local/file.jpg" \
  http://127.0.0.1:8888/path/to/upload/

# 示例 (使用 jwt 查询参数)
curl -X POST \
  -F "file=@/path/to/your/local/file.jpg" \
  http://127.0.0.1:8888/path/to/upload?jwt=eyJ0eXAiO4JKV1QiLCJhbGciO3JIUzI1NiJ9.e30.xtrTYsadhSeqg6bjBR4gMUkIETvADSI1EJQItCP8Uds

filer 启用 JWT 后的文件下载

格式:这里要用读操作的 JWT 令牌。即通过 jwt.filer_signing.read.key 生成的 token

shell
curl -X GET \
  -H "Authorization: Bearer 你的读操作JWT令牌" \
  -o downloaded_file.jpg \
  http://127.0.0.1:8888/path/to/your/file.jpg
shell
# 示例 (Authorization 请求头)
curl -X GET \
  -H "Authorization: Bearer eyJ0eXAiO4JKV1QiLCJhbGciO3JIUzI1NiJ9.e30.xtrTYsadhSeqg6bjBR4gMUkIETvADSI1EJQItCP8Uds" \
  -o downloaded_file.jpg \
  http://127.0.0.1:8888/path/to/your/file.jpg

# 示例 (jwt 查询参数)
curl -X GET \
  -o downloaded_file.jpg \
  http://127.0.0.1:8888/path/to/your/file.jpg?jwt=eyJ0eXAiO4JKV1QiLCJhbGciO3JIUzI1NiJ9.e30.xtrTYsadhSeqg6bjBR4gMUkIETvADSI1EJQItCP8Uds

# 使用浏览器访问下载
http://127.0.0.1:8888/path/to/your/file.jpg?jwt=你的读操作JWT令牌